From 76d3fcfbb6cb623da8589e462ae47ddb89c5b335 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Thu, 14 Feb 2019 18:59:52 +0100 Subject: [PATCH 001/220] Re-add configuration page for OpenSubtitles --- src/opensubtitles.html | 36 ++++++++++++++++++++++++++++++++++++ src/scripts/librarymenu.js | 5 +++++ src/scripts/opensubtitles.js | 36 ++++++++++++++++++++++++++++++++++++ src/scripts/site.js | 5 +++++ 4 files changed, 82 insertions(+) create mode 100644 src/opensubtitles.html create mode 100644 src/scripts/opensubtitles.js diff --git a/src/opensubtitles.html b/src/opensubtitles.html new file mode 100644 index 0000000000..33915b790d --- /dev/null +++ b/src/opensubtitles.html @@ -0,0 +1,36 @@ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + +
+
+ + +
+ +
+ +
+ +
+ +
+
${SubtitleDownloadInstructions}
+
+
+ +
+
diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index 18fafa8bf6..8d65f9420b 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -297,6 +297,11 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " icon: "swap_horiz", href: "encodingsettings.html", pageIds: ["encodingSettingsPage"] + }, { + name: "Open Subtitles", + href: "opensubtitles.html", + pageIds: ["openSubtitlesPage"], + icon: "closed_caption" }]; addPluginPagesToMainMenu(links, pluginItems, "server"); links.push({ diff --git a/src/scripts/opensubtitles.js b/src/scripts/opensubtitles.js new file mode 100644 index 0000000000..d06f8a44da --- /dev/null +++ b/src/scripts/opensubtitles.js @@ -0,0 +1,36 @@ +define(["loading", "fnchecked", "emby-linkbutton", "emby-input", "emby-checkbox", "emby-button"], function (loading) { + "use strict"; + + function loadPage(page, config) { + page.querySelector("#txtOpenSubtitleUsername").value = config.OpenSubtitlesUsername; + page.querySelector("#txtOpenSubtitlePassword").value = config.OpenSubtitlesPasswordHash || ""; + loading.hide(); + } + + function onSubmit(e__q) { + e__q.preventDefault(); + loading.show(); + var form = this; + ApiClient.getNamedConfiguration("subtitles").then(function (config) { + config.OpenSubtitlesUsername = form.querySelector("#txtOpenSubtitleUsername").value; + var newPassword = form.querySelector("#txtOpenSubtitlePassword").value; + + if (newPassword) { + config.OpenSubtitlesPasswordHash = newPassword; + } + + ApiClient.updateNamedConfiguration("subtitles", config).then(Dashboard.processServerConfigurationUpdateResult); + }); + return false; + } + + $(document).on("pageinit", "#openSubtitlesPage", function() { + $(".metadataSubtitlesForm").off("submit", onSubmit).on("submit", onSubmit) + }).on("pageshow", "#openSubtitlesPage", function() { + loading.show(); + var page = this; + ApiClient.getNamedConfiguration("subtitles").then(function (response) { + loadPage(page, response); + }); + }); +}); diff --git a/src/scripts/site.js b/src/scripts/site.js index 885529cdff..573464ec2c 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -512,6 +512,11 @@ var Dashboard = { dependencies: [], autoFocus: !1, roles: "admin" + }), defineRoute({ + path: "/opensubtitles.html", + dependencies: [], + autoFocus: !1, + roles: "admin" }), defineRoute({ path: "/forgotpassword.html", dependencies: ["emby-input", "emby-button"], From fbb793e4455275bc2f768c9456a95ba39d10ec63 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Thu, 14 Feb 2019 19:02:43 +0100 Subject: [PATCH 002/220] Hardcode Register string since ButtonRegister has been removed from strings --- src/opensubtitles.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/opensubtitles.html b/src/opensubtitles.html index 33915b790d..7c9902ea7f 100644 --- a/src/opensubtitles.html +++ b/src/opensubtitles.html @@ -17,7 +17,8 @@ From ec57b8c493545fe8b941d0f96bbdc5a374cfa08e Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Thu, 14 Feb 2019 19:05:09 +0100 Subject: [PATCH 003/220] Removed some newlines and manual deuglification --- src/opensubtitles.html | 9 --------- src/scripts/opensubtitles.js | 4 ++-- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/opensubtitles.html b/src/opensubtitles.html index 7c9902ea7f..5174a1f1de 100644 --- a/src/opensubtitles.html +++ b/src/opensubtitles.html @@ -1,18 +1,12 @@ 
-
-
-
-
- -
@@ -21,17 +15,14 @@ Register
-
-
${SubtitleDownloadInstructions}
-
diff --git a/src/scripts/opensubtitles.js b/src/scripts/opensubtitles.js index d06f8a44da..99ec982dc1 100644 --- a/src/scripts/opensubtitles.js +++ b/src/scripts/opensubtitles.js @@ -7,8 +7,8 @@ define(["loading", "fnchecked", "emby-linkbutton", "emby-input", "emby-checkbox" loading.hide(); } - function onSubmit(e__q) { - e__q.preventDefault(); + function onSubmit(evt) { + evt.preventDefault(); loading.show(); var form = this; ApiClient.getNamedConfiguration("subtitles").then(function (config) { From 3e313972bc96d5cd7d34f3fb0911edb7339a3ccb Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Fri, 15 Feb 2019 12:11:16 +0100 Subject: [PATCH 004/220] Add ButtonRegister string --- src/strings/en-us.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 801ae50280..17285da845 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -159,6 +159,7 @@ "ButtonReenable": "Re-enable", "ButtonRefresh": "Refresh", "ButtonRefreshGuideData": "Refresh Guide Data", + "ButtonRegister": "Register", "ButtonReject": "Reject", "ButtonRemote": "Remote", "ButtonRemoteControl": "Remote Control", @@ -2264,4 +2265,4 @@ "XmlTvSportsCategoriesHelp": "Programs with these categories will be displayed as sports programs. Separate multiple with '|'.", "Yes": "Yes", "Yesterday": "Yesterday" -} \ No newline at end of file +} From 7df3a87230c7da01deb48486dfe892cf64b2140d Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Fri, 15 Feb 2019 12:11:58 +0100 Subject: [PATCH 005/220] Replace Register with ButtonRegister translation key --- src/opensubtitles.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/opensubtitles.html b/src/opensubtitles.html index 5174a1f1de..51e337ae63 100644 --- a/src/opensubtitles.html +++ b/src/opensubtitles.html @@ -11,8 +11,7 @@
From 53fbc24ac547fce2db8a08a683c4402284b537d8 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Sun, 17 Feb 2019 23:13:42 +0100 Subject: [PATCH 006/220] Exit fullscreen automatically when video playback stops --- .../emby-webcomponents/htmlvideoplayer/plugin.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bower_components/emby-webcomponents/htmlvideoplayer/plugin.js b/src/bower_components/emby-webcomponents/htmlvideoplayer/plugin.js index 19b075b622..e723790583 100644 --- a/src/bower_components/emby-webcomponents/htmlvideoplayer/plugin.js +++ b/src/bower_components/emby-webcomponents/htmlvideoplayer/plugin.js @@ -1,4 +1,4 @@ -define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackManager', 'appRouter', 'appSettings', 'connectionManager', 'htmlMediaHelper', 'itemHelper'], function (browser, require, events, appHost, loading, dom, playbackManager, appRouter, appSettings, connectionManager, htmlMediaHelper, itemHelper) { +define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackManager', 'appRouter', 'appSettings', 'connectionManager', 'htmlMediaHelper', 'itemHelper', 'fullscreenManager'], function (browser, require, events, appHost, loading, dom, playbackManager, appRouter, appSettings, connectionManager, htmlMediaHelper, itemHelper, fullscreenManager) { "use strict"; var mediaManager; @@ -692,6 +692,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa dlg.parentNode.removeChild(dlg); } + fullscreenManager.exitFullscreen(); }; function onEnded() { From 9a7ede5536700c711884386af60dda22dae302b3 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Sun, 17 Feb 2019 23:29:31 +0100 Subject: [PATCH 007/220] Add fullscreen check to avoid errors in Chrome --- .../fullscreen/fullscreenmanager.js | 17 +++++++++++++---- .../htmlvideoplayer/plugin.js | 1 + 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/bower_components/emby-webcomponents/fullscreen/fullscreenmanager.js b/src/bower_components/emby-webcomponents/fullscreen/fullscreenmanager.js index d39d8fd3b6..5773e57d07 100644 --- a/src/bower_components/emby-webcomponents/fullscreen/fullscreenmanager.js +++ b/src/bower_components/emby-webcomponents/fullscreen/fullscreenmanager.js @@ -29,11 +29,14 @@ define(['events', 'dom'], function (events, dom) { } if (element.webkitEnterFullscreen) { element.webkitEnterFullscreen(); - } + } }; fullscreenManager.prototype.exitFullscreen = function () { + if (!this.isFullScreen()) { + return; + } if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.mozCancelFullScreen) { @@ -47,9 +50,15 @@ define(['events', 'dom'], function (events, dom) { } }; + // TODO: use screenfull.js fullscreenManager.prototype.isFullScreen = function () { - - return document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement ? true : false; + return document.fullscreen || + document.mozFullScreen || + document.webkitIsFullScreen || + document.msFullscreenElement || /* IE/Edge syntax */ + document.fullscreenElement || /* Standard syntax */ + document.webkitFullscreenElement || /* Chrome, Safari and Opera syntax */ + document.mozFullScreenElement; /* Firefox syntax */ }; var manager = new fullscreenManager(); @@ -71,4 +80,4 @@ define(['events', 'dom'], function (events, dom) { }); return manager; -}); \ No newline at end of file +}); diff --git a/src/bower_components/emby-webcomponents/htmlvideoplayer/plugin.js b/src/bower_components/emby-webcomponents/htmlvideoplayer/plugin.js index e723790583..d25b49163b 100644 --- a/src/bower_components/emby-webcomponents/htmlvideoplayer/plugin.js +++ b/src/bower_components/emby-webcomponents/htmlvideoplayer/plugin.js @@ -692,6 +692,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa dlg.parentNode.removeChild(dlg); } + fullscreenManager.exitFullscreen(); }; From d2fe0e4bef3b282fa5daab255119dd28e82a19e4 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 19 Feb 2019 00:37:38 +0300 Subject: [PATCH 008/220] margining top offset and bottom offset emby-scrollbuttons --- .../emby-scrollbuttons/emby-scrollbuttons.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bower_components/emby-webcomponents/emby-scrollbuttons/emby-scrollbuttons.css b/src/bower_components/emby-webcomponents/emby-scrollbuttons/emby-scrollbuttons.css index 5e404e780d..04b2ce68c6 100644 --- a/src/bower_components/emby-webcomponents/emby-scrollbuttons/emby-scrollbuttons.css +++ b/src/bower_components/emby-webcomponents/emby-scrollbuttons/emby-scrollbuttons.css @@ -4,8 +4,8 @@ .scrollbuttoncontainer { position: absolute; - top: 0; - bottom: 0; + top: 10%; + bottom: 35%; align-items: center; justify-content: center; z-index: 1; From 907a4ec516e885093c6596a1bd6df5a7d6356a3a Mon Sep 17 00:00:00 2001 From: Vasily Date: Tue, 19 Feb 2019 18:58:58 +0300 Subject: [PATCH 009/220] Copy issue and PR templates from main repo --- .github/ISSUE_TEMPLATE/bug_report.md | 35 +++++++++++++++++++ .github/ISSUE_TEMPLATE/enhancement-request.md | 20 +++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 14 ++++++++ .github/pull_request_template.md | 11 ++++++ 4 files changed, 80 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/enhancement-request.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/pull_request_template.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000..137a689e8b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,35 @@ +--- +name: Bug report +about: Create a bug report +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** + + +**To Reproduce** + +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** + + +**Logs** + + +**Screenshots** + + +**System (please complete the following information):** + - OS: [e.g. Docker, Debian, Windows] + - Browser: [e.g. Firefox, Chrome, Safari] + - Jellyfin Version: [e.g. 10.0.1] + +**Additional context** + diff --git a/.github/ISSUE_TEMPLATE/enhancement-request.md b/.github/ISSUE_TEMPLATE/enhancement-request.md new file mode 100644 index 0000000000..a655b60f53 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/enhancement-request.md @@ -0,0 +1,20 @@ +--- +name: Enhancement request +about: Suggest an modification to an existing feature +title: '' +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** + + +**Describe the solution you'd like** + + +**Describe alternatives you've considered** + + +**Additional context** + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000..3cbc8cbb91 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,14 @@ +--- +name: Feature request +about: Suggest a new feature +title: '' +labels: feature +assignees: '' + +--- + +**Describe the feature you'd like** + + +**Additional context** + diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000000..967be0fb73 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,11 @@ + + +**Changes** + + +**Issues** + From 4dd77a24ab557be320bcc6462b05e20293ee0cf8 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Wed, 20 Feb 2019 22:15:40 +0000 Subject: [PATCH 010/220] added package.json with yarn init --- package.json | 7 +++++++ yarn.lock | 4 ++++ 2 files changed, 11 insertions(+) create mode 100644 package.json create mode 100644 yarn.lock diff --git a/package.json b/package.json new file mode 100644 index 0000000000..2d7e1a92e5 --- /dev/null +++ b/package.json @@ -0,0 +1,7 @@ +{ + "name": "jellyfin-web", + "version": "10.2.1", + "description": "Web interface for Jellyfin", + "repository": "https://github.com/jellyfin/jellyfin-web", + "license": "GPL-2" +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000000..fb57ccd13a --- /dev/null +++ b/yarn.lock @@ -0,0 +1,4 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + From 7f407f96915e425f814260aaefa3973ece4f8acd Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Wed, 20 Feb 2019 22:17:26 +0000 Subject: [PATCH 011/220] added weback and webpack-cli as dev dependencies --- package.json | 6 +- yarn.lock | 2841 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2846 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 2d7e1a92e5..b4deb41d86 100644 --- a/package.json +++ b/package.json @@ -3,5 +3,9 @@ "version": "10.2.1", "description": "Web interface for Jellyfin", "repository": "https://github.com/jellyfin/jellyfin-web", - "license": "GPL-2" + "license": "GPL-2", + "devDependencies": { + "webpack": "^4.29.5", + "webpack-cli": "^3.2.3" + } } diff --git a/yarn.lock b/yarn.lock index fb57ccd13a..a5cd7a677b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,3 +2,2844 @@ # yarn lockfile v1 +"@webassemblyjs/ast@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.3.tgz#63a741bd715a6b6783f2ea5c6ab707516aa215eb" + integrity sha512-xy3m06+Iu4D32+6soz6zLnwznigXJRuFNTovBX2M4GqVqLb0dnyWLbPnpcXvUSdEN+9DVyDeaq2jyH1eIL2LZQ== + dependencies: + "@webassemblyjs/helper-module-context" "1.8.3" + "@webassemblyjs/helper-wasm-bytecode" "1.8.3" + "@webassemblyjs/wast-parser" "1.8.3" + +"@webassemblyjs/floating-point-hex-parser@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.3.tgz#f198a2d203b3c50846a064f5addd6a133ef9bc0e" + integrity sha512-vq1TISG4sts4f0lDwMUM0f3kpe0on+G3YyV5P0IySHFeaLKRYZ++n2fCFfG4TcCMYkqFeTUYFxm75L3ddlk2xA== + +"@webassemblyjs/helper-api-error@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.3.tgz#3b708f6926accd64dcbaa7ba5b63db5660ff4f66" + integrity sha512-BmWEynI4FnZbjk8CaYZXwcv9a6gIiu+rllRRouQUo73hglanXD3AGFJE7Q4JZCoVE0p5/jeX6kf5eKa3D4JxwQ== + +"@webassemblyjs/helper-buffer@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.3.tgz#f3150a23ffaba68621e1f094c8a14bebfd53dd48" + integrity sha512-iVIMhWnNHoFB94+/2l7LpswfCsXeMRnWfExKtqsZ/E2NxZyUx9nTeKK/MEMKTQNEpyfznIUX06OchBHQ+VKi/Q== + +"@webassemblyjs/helper-code-frame@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.3.tgz#f43ac605789b519d95784ef350fd2968aebdd3ef" + integrity sha512-K1UxoJML7GKr1QXR+BG7eXqQkvu+eEeTjlSl5wUFQ6W6vaOc5OwSxTcb3oE9x/3+w4NHhrIKD4JXXCZmLdL2cg== + dependencies: + "@webassemblyjs/wast-printer" "1.8.3" + +"@webassemblyjs/helper-fsm@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.3.tgz#46aaa03f41082a916850ebcb97e9fc198ef36a9c" + integrity sha512-387zipfrGyO77/qm7/SDUiZBjQ5KGk4qkrVIyuoubmRNIiqn3g+6ijY8BhnlGqsCCQX5bYKOnttJobT5xoyviA== + +"@webassemblyjs/helper-module-context@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.3.tgz#150da405d90c8ea81ae0b0e1965b7b64e585634f" + integrity sha512-lPLFdQfaRssfnGEJit5Sk785kbBPPPK4ZS6rR5W/8hlUO/5v3F+rN8XuUcMj/Ny9iZiyKhhuinWGTUuYL4VKeQ== + dependencies: + "@webassemblyjs/ast" "1.8.3" + mamacro "^0.0.3" + +"@webassemblyjs/helper-wasm-bytecode@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.3.tgz#12f55bbafbbc7ddf9d8059a072cb7b0c17987901" + integrity sha512-R1nJW7bjyJLjsJQR5t3K/9LJ0QWuZezl8fGa49DZq4IVaejgvkbNlKEQxLYTC579zgT4IIIVHb5JA59uBPHXyw== + +"@webassemblyjs/helper-wasm-section@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.3.tgz#9e79456d9719e116f4f8998ee62ab54ba69a6cf3" + integrity sha512-P6F7D61SJY73Yz+fs49Q3+OzlYAZP86OfSpaSY448KzUy65NdfzDmo2NPVte+Rw4562MxEAacvq/mnDuvRWOcg== + dependencies: + "@webassemblyjs/ast" "1.8.3" + "@webassemblyjs/helper-buffer" "1.8.3" + "@webassemblyjs/helper-wasm-bytecode" "1.8.3" + "@webassemblyjs/wasm-gen" "1.8.3" + +"@webassemblyjs/ieee754@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.3.tgz#0a89355b1f6c9d08d0605c2acbc2a6fe3141f5b4" + integrity sha512-UD4HuLU99hjIvWz1pD68b52qsepWQlYCxDYVFJQfHh3BHyeAyAlBJ+QzLR1nnS5J6hAzjki3I3AoJeobNNSZlg== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.3.tgz#b7fd9d7c039e34e375c4473bd4dc89ce8228b920" + integrity sha512-XXd3s1BmkC1gpGABuCRLqCGOD6D2L+Ma2BpwpjrQEHeQATKWAQtxAyU9Z14/z8Ryx6IG+L4/NDkIGHrccEhRUg== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.3.tgz#75712db52cfdda868731569ddfe11046f1f1e7a2" + integrity sha512-Wv/WH9Zo5h5ZMyfCNpUrjFsLZ3X1amdfEuwdb7MLdG3cPAjRS6yc6ElULlpjLiiBTuzvmLhr3ENsuGyJ3wyCgg== + +"@webassemblyjs/wasm-edit@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.3.tgz#23c3c6206b096f9f6aa49623a5310a102ef0fb87" + integrity sha512-nB19eUx3Yhi1Vvv3yev5r+bqQixZprMtaoCs1brg9Efyl8Hto3tGaUoZ0Yb4Umn/gQCyoEGFfUxPLp1/8+Jvnw== + dependencies: + "@webassemblyjs/ast" "1.8.3" + "@webassemblyjs/helper-buffer" "1.8.3" + "@webassemblyjs/helper-wasm-bytecode" "1.8.3" + "@webassemblyjs/helper-wasm-section" "1.8.3" + "@webassemblyjs/wasm-gen" "1.8.3" + "@webassemblyjs/wasm-opt" "1.8.3" + "@webassemblyjs/wasm-parser" "1.8.3" + "@webassemblyjs/wast-printer" "1.8.3" + +"@webassemblyjs/wasm-gen@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.3.tgz#1a433b8ab97e074e6ac2e25fcbc8cb6125400813" + integrity sha512-sDNmu2nLBJZ/huSzlJvd9IK8B1EjCsOl7VeMV9VJPmxKYgTJ47lbkSP+KAXMgZWGcArxmcrznqm7FrAPQ7vVGg== + dependencies: + "@webassemblyjs/ast" "1.8.3" + "@webassemblyjs/helper-wasm-bytecode" "1.8.3" + "@webassemblyjs/ieee754" "1.8.3" + "@webassemblyjs/leb128" "1.8.3" + "@webassemblyjs/utf8" "1.8.3" + +"@webassemblyjs/wasm-opt@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.3.tgz#54754bcf88f88e92b909416a91125301cc81419c" + integrity sha512-j8lmQVFR+FR4/645VNgV4R/Jz8i50eaPAj93GZyd3EIJondVshE/D9pivpSDIXyaZt+IkCodlzOoZUE4LnQbeA== + dependencies: + "@webassemblyjs/ast" "1.8.3" + "@webassemblyjs/helper-buffer" "1.8.3" + "@webassemblyjs/wasm-gen" "1.8.3" + "@webassemblyjs/wasm-parser" "1.8.3" + +"@webassemblyjs/wasm-parser@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.3.tgz#d12ed19d1b8e8667a7bee040d2245aaaf215340b" + integrity sha512-NBI3SNNtRoy4T/KBsRZCAWUzE9lI94RH2nneLwa1KKIrt/2zzcTavWg6oY05ArCbb/PZDk3OUi63CD1RYtN65w== + dependencies: + "@webassemblyjs/ast" "1.8.3" + "@webassemblyjs/helper-api-error" "1.8.3" + "@webassemblyjs/helper-wasm-bytecode" "1.8.3" + "@webassemblyjs/ieee754" "1.8.3" + "@webassemblyjs/leb128" "1.8.3" + "@webassemblyjs/utf8" "1.8.3" + +"@webassemblyjs/wast-parser@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.3.tgz#44aa123e145503e995045dc3e5e2770069da117b" + integrity sha512-gZPst4CNcmGtKC1eYQmgCx6gwQvxk4h/nPjfPBbRoD+Raw3Hs+BS3yhrfgyRKtlYP+BJ8LcY9iFODEQofl2qbg== + dependencies: + "@webassemblyjs/ast" "1.8.3" + "@webassemblyjs/floating-point-hex-parser" "1.8.3" + "@webassemblyjs/helper-api-error" "1.8.3" + "@webassemblyjs/helper-code-frame" "1.8.3" + "@webassemblyjs/helper-fsm" "1.8.3" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/wast-printer@1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.3.tgz#b1177780b266b1305f2eeba87c4d6aa732352060" + integrity sha512-DTA6kpXuHK4PHu16yAD9QVuT1WZQRT7079oIFFmFSjqjLWGXS909I/7kiLTn931mcj7wGsaUNungjwNQ2lGQ3Q== + dependencies: + "@webassemblyjs/ast" "1.8.3" + "@webassemblyjs/wast-parser" "1.8.3" + "@xtuc/long" "4.2.2" + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +acorn-dynamic-import@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" + integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== + +acorn@^6.0.5: + version "6.1.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.0.tgz#b0a3be31752c97a0f7013c5f4903b71a05db6818" + integrity sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw== + +ajv-errors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== + +ajv-keywords@^3.1.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.0.tgz#4b831e7b531415a7cc518cd404e73f6193c6349d" + integrity sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw== + +ajv@^6.1.0: + version "6.9.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.9.1.tgz#a4d3683d74abc5670e75f0b16520f70a20ea8dc1" + integrity sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +aproba@^1.0.3, aproba@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +asn1.js@^4.0.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +assert@^1.1.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" + integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE= + dependencies: + util "0.10.3" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +async-each@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + integrity sha1-GdOGodntxufByF04iu28xW0zYC0= + +atob@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base64-js@^1.0.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" + integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +binary-extensions@^1.0.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.0.tgz#9523e001306a32444b907423f1de2164222f6ab1" + integrity sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw== + +bluebird@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" + integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw== + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +brorand@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= + dependencies: + bn.js "^4.1.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" + integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= + dependencies: + bn.js "^4.1.1" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.2" + elliptic "^6.0.0" + inherits "^2.0.1" + parse-asn1 "^5.0.0" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer@^4.3.0: + version "4.9.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" + integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + +cacache@^11.0.2: + version "11.3.2" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.2.tgz#2d81e308e3d258ca38125b676b98b2ac9ce69bfa" + integrity sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg== + dependencies: + bluebird "^3.5.3" + chownr "^1.1.1" + figgy-pudding "^3.5.1" + glob "^7.1.3" + graceful-fs "^4.1.15" + lru-cache "^5.1.1" + mississippi "^3.0.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.2" + ssri "^6.0.1" + unique-filename "^1.1.1" + y18n "^4.0.0" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +camelcase@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" + integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== + +chalk@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chokidar@^2.0.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.2.tgz#9c23ea40b01638439e0513864d362aeacc5ad058" + integrity sha512-IwXUx0FXc5ibYmPC2XeEj5mpXoV66sR+t3jqu2NS2GYwCktt3KF1/Qqjws/NkegajBA4RbZ5+DDwlOiJsxDHEg== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.0" + optionalDependencies: + fsevents "^1.2.7" + +chownr@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" + integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== + +chrome-trace-event@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz#45a91bd2c20c9411f0963b5aaeb9a1b95e09cc48" + integrity sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A== + dependencies: + tslib "^1.9.0" + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cliui@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +commander@~2.17.1: + version "2.17.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" + integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + +component-emitter@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.5.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +console-browserify@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= + dependencies: + date-now "^0.1.4" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + +copy-concurrently@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== + dependencies: + aproba "^1.1.1" + fs-write-stream-atomic "^1.0.8" + iferr "^0.1.5" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.0" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +create-ecdh@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" + integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== + dependencies: + bn.js "^4.1.0" + elliptic "^6.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cross-spawn@^6.0.0, cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +cyclist@~0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" + integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= + +debug@^2.1.2, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +des.js@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" + integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +detect-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + +duplexify@^3.4.2, duplexify@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +elliptic@^6.0.0: + version "6.4.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" + integrity sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ== + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + +emojis-list@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + dependencies: + once "^1.4.0" + +enhanced-resolve@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" + integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.4.0" + tapable "^1.0.0" + +errno@^0.1.3, errno@~0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== + dependencies: + prr "~1.0.1" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +eslint-scope@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" + integrity sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +estraverse@^4.1.0, estraverse@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= + +events@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" + integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expand-tilde@^2.0.0, expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= + dependencies: + homedir-polyfill "^1.0.1" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + +figgy-pudding@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" + integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +find-cache-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.0.0.tgz#4c1faed59f45184530fb9d7fa123a4d04a98472d" + integrity sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA== + dependencies: + commondir "^1.0.1" + make-dir "^1.0.0" + pkg-dir "^3.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +findup-sync@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" + integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= + dependencies: + detect-file "^1.0.0" + is-glob "^3.1.0" + micromatch "^3.0.4" + resolve-dir "^1.0.1" + +flush-write-stream@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== + dependencies: + inherits "^2.0.3" + readable-stream "^2.3.6" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +from2@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-minipass@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== + dependencies: + minipass "^2.2.1" + +fs-write-stream-atomic@^1.0.8: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= + dependencies: + graceful-fs "^4.1.2" + iferr "^0.1.5" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.7.tgz#4851b664a3783e52003b3c66eb0eee1074933aa4" + integrity sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw== + dependencies: + nan "^2.9.2" + node-pre-gyp "^0.10.0" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-modules@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== + dependencies: + global-prefix "^1.0.1" + is-windows "^1.0.1" + resolve-dir "^1.0.0" + +global-prefix@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= + dependencies: + expand-tilde "^2.0.2" + homedir-polyfill "^1.0.1" + ini "^1.3.4" + is-windows "^1.0.1" + which "^1.2.14" + +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: + version "4.1.15" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" + integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +hash-base@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hmac-drbg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +homedir-polyfill@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" + integrity sha1-TCu8inWJmP7r9e1oWA921GdotLw= + dependencies: + parse-passwd "^1.0.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= + +iconv-lite@^0.4.4: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ieee754@^1.1.4: + version "1.1.12" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" + integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA== + +iferr@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= + +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== + dependencies: + minimatch "^3.0.4" + +import-local@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" + integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== + dependencies: + pkg-dir "^3.0.0" + resolve-cwd "^2.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +indexof@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" + integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= + +ini@^1.3.4, ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +interpret@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" + integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== + +invert-kv@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" + integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" + integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= + dependencies: + is-extglob "^2.1.1" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-windows@^1.0.1, is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + +lcid@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" + integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== + dependencies: + invert-kv "^2.0.0" + +loader-runner@^2.3.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" + integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== + +loader-utils@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" + integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== + dependencies: + big.js "^5.2.2" + emojis-list "^2.0.0" + json5 "^1.0.1" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +make-dir@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== + dependencies: + pify "^3.0.0" + +mamacro@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" + integrity sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA== + +map-age-cleaner@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + dependencies: + p-defer "^1.0.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +mem@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.1.0.tgz#aeb9be2d21f47e78af29e4ac5978e8afa2ca5b8a" + integrity sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg== + dependencies: + map-age-cleaner "^0.1.1" + mimic-fn "^1.0.0" + p-is-promise "^2.0.0" + +memory-fs@^0.4.0, memory-fs@~0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + +minipass@^2.2.1, minipass@^2.3.4: + version "2.3.5" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" + integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" + integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== + dependencies: + minipass "^2.2.1" + +mississippi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== + dependencies: + concat-stream "^1.5.0" + duplexify "^3.4.2" + end-of-stream "^1.1.0" + flush-write-stream "^1.0.0" + from2 "^2.1.0" + parallel-transform "^1.1.0" + pump "^3.0.0" + pumpify "^1.3.3" + stream-each "^1.1.0" + through2 "^2.0.0" + +mixin-deep@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +move-concurrently@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= + dependencies: + aproba "^1.1.1" + copy-concurrently "^1.0.0" + fs-write-stream-atomic "^1.0.8" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.3" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +nan@^2.9.2: + version "2.12.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" + integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +needle@^2.2.1: + version "2.2.4" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" + integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" + +neo-async@^2.5.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835" + integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-libs-browser@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.0.tgz#c72f60d9d46de08a940dedbb25f3ffa2f9bbaa77" + integrity sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA== + dependencies: + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^3.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.0" + process "^0.11.10" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.3.3" + stream-browserify "^2.0.1" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.11.0" + vm-browserify "0.0.4" + +node-pre-gyp@^0.10.0: + version "0.10.3" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" + integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-bundled@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" + integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== + +npm-packlist@^1.1.6: + version "1.4.1" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.1.tgz#19064cdf988da80ea3cee45533879d90192bbfbc" + integrity sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-locale@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" + integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== + dependencies: + execa "^1.0.0" + lcid "^2.0.0" + mem "^4.0.0" + +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-is-promise@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.0.0.tgz#7554e3d572109a87e1f3f53f6a7d85d1b194f4c5" + integrity sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg== + +p-limit@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.1.0.tgz#1d5a0d20fb12707c758a655f6bbc4386b5930d68" + integrity sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g== + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-try@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" + integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ== + +pako@~1.0.5: + version "1.0.8" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.8.tgz#6844890aab9c635af868ad5fecc62e8acbba3ea4" + integrity sha512-6i0HVbUfcKaTv+EG8ZTr75az7GFXcLYk9UyLEg7Notv/Ma+z/UG3TCoz6GiNeOrn1E/e63I0X/Hpw18jHOTUnA== + +parallel-transform@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06" + integrity sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY= + dependencies: + cyclist "~0.2.2" + inherits "^2.0.3" + readable-stream "^2.1.5" + +parse-asn1@^5.0.0: + version "5.1.4" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc" + integrity sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw== + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" + integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo= + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +pbkdf2@^3.0.3: + version "3.0.17" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" + integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@^1.2.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + +resolve-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= + dependencies: + resolve-from "^3.0.0" + +resolve-dir@^1.0.0, resolve-dir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= + dependencies: + expand-tilde "^2.0.0" + global-modules "^1.0.0" + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +run-queue@^1.0.0, run-queue@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= + dependencies: + aproba "^1.1.1" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +schema-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== + dependencies: + ajv "^6.1.0" + ajv-errors "^1.0.0" + ajv-keywords "^3.1.0" + +semver@^5.3.0, semver@^5.5.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" + integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== + +serialize-javascript@^1.4.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.6.1.tgz#4d1f697ec49429a847ca6f442a2a755126c4d879" + integrity sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw== + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-value@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.1" + to-object-path "^0.3.0" + +set-value@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +source-list-map@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@~0.5.9: + version "0.5.10" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c" + integrity sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +ssri@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" + integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== + dependencies: + figgy-pudding "^3.5.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +stream-browserify@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-each@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== + dependencies: + end-of-stream "^1.1.0" + stream-shift "^1.0.0" + +stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +stream-shift@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string_decoder@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" + integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== + dependencies: + safe-buffer "~5.1.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +supports-color@^5.3.0, supports-color@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +tapable@^1.0.0, tapable@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.1.tgz#4d297923c5a72a42360de2ab52dadfaaec00018e" + integrity sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA== + +tar@^4: + version "4.4.8" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" + integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ== + dependencies: + chownr "^1.1.1" + fs-minipass "^1.2.5" + minipass "^2.3.4" + minizlib "^1.1.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.2" + +terser-webpack-plugin@^1.1.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.2.2.tgz#9bff3a891ad614855a7dde0d707f7db5a927e3d9" + integrity sha512-1DMkTk286BzmfylAvLXwpJrI7dWa5BnFmscV/2dCr8+c56egFcbaeFAl7+sujAjdmpLam21XRdhA4oifLyiWWg== + dependencies: + cacache "^11.0.2" + find-cache-dir "^2.0.0" + schema-utils "^1.0.0" + serialize-javascript "^1.4.0" + source-map "^0.6.1" + terser "^3.16.1" + webpack-sources "^1.1.0" + worker-farm "^1.5.2" + +terser@^3.16.1: + version "3.16.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-3.16.1.tgz#5b0dd4fa1ffd0b0b43c2493b2c364fd179160493" + integrity sha512-JDJjgleBROeek2iBcSNzOHLKsB/MdDf+E/BOAJ0Tk9r7p9/fVobfv7LMJ/g/k3v9SXdmjZnIlFd5nfn/Rt0Xow== + dependencies: + commander "~2.17.1" + source-map "~0.6.1" + source-map-support "~0.5.9" + +through2@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +timers-browserify@^2.0.4: + version "2.0.10" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" + integrity sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg== + dependencies: + setimmediate "^1.0.4" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +tslib@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" + integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +union-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^0.4.3" + +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.1.tgz#5e9edc6d1ce8fb264db18a507ef9bd8544451ca6" + integrity sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg== + dependencies: + imurmurhash "^0.1.4" + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +upath@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" + integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= + dependencies: + inherits "2.0.1" + +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== + dependencies: + inherits "2.0.3" + +v8-compile-cache@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c" + integrity sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw== + +vm-browserify@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" + integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM= + dependencies: + indexof "0.0.1" + +watchpack@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" + integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== + dependencies: + chokidar "^2.0.2" + graceful-fs "^4.1.2" + neo-async "^2.5.0" + +webpack-cli@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.2.3.tgz#13653549adfd8ccd920ad7be1ef868bacc22e346" + integrity sha512-Ik3SjV6uJtWIAN5jp5ZuBMWEAaP5E4V78XJ2nI+paFPh8v4HPSwo/myN0r29Xc/6ZKnd2IdrAlpSgNOu2CDQ6Q== + dependencies: + chalk "^2.4.1" + cross-spawn "^6.0.5" + enhanced-resolve "^4.1.0" + findup-sync "^2.0.0" + global-modules "^1.0.0" + import-local "^2.0.0" + interpret "^1.1.0" + loader-utils "^1.1.0" + supports-color "^5.5.0" + v8-compile-cache "^2.0.2" + yargs "^12.0.4" + +webpack-sources@^1.1.0, webpack-sources@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" + integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack@^4.29.5: + version "4.29.5" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.29.5.tgz#52b60a7b0838427c3a894cd801a11dc0836bc79f" + integrity sha512-DuWlYUT982c7XVHodrLO9quFbNpVq5FNxLrMUfYUTlgKW0+yPimynYf1kttSQpEneAL1FH3P3OLNgkyImx8qIQ== + dependencies: + "@webassemblyjs/ast" "1.8.3" + "@webassemblyjs/helper-module-context" "1.8.3" + "@webassemblyjs/wasm-edit" "1.8.3" + "@webassemblyjs/wasm-parser" "1.8.3" + acorn "^6.0.5" + acorn-dynamic-import "^4.0.0" + ajv "^6.1.0" + ajv-keywords "^3.1.0" + chrome-trace-event "^1.0.0" + enhanced-resolve "^4.1.0" + eslint-scope "^4.0.0" + json-parse-better-errors "^1.0.2" + loader-runner "^2.3.0" + loader-utils "^1.1.0" + memory-fs "~0.4.1" + micromatch "^3.1.8" + mkdirp "~0.5.0" + neo-async "^2.5.0" + node-libs-browser "^2.0.0" + schema-utils "^1.0.0" + tapable "^1.1.0" + terser-webpack-plugin "^1.1.0" + watchpack "^1.5.0" + webpack-sources "^1.3.0" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@^1.2.14, which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +worker-farm@^1.5.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0" + integrity sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ== + dependencies: + errno "~0.1.7" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +xtend@^4.0.0, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= + +"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yallist@^3.0.0, yallist@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" + integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== + +yargs-parser@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" + integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@^12.0.4: + version "12.0.5" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" + integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== + dependencies: + cliui "^4.0.0" + decamelize "^1.2.0" + find-up "^3.0.0" + get-caller-file "^1.0.1" + os-locale "^3.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1 || ^4.0.0" + yargs-parser "^11.1.1" From f5c2a331b0f69c92202aa6c622e2885ed3e6e7ba Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Wed, 20 Feb 2019 22:18:56 +0000 Subject: [PATCH 012/220] changed package.json for initial version 0.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b4deb41d86..1816b6ea91 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jellyfin-web", - "version": "10.2.1", + "version": "0.0.0", "description": "Web interface for Jellyfin", "repository": "https://github.com/jellyfin/jellyfin-web", "license": "GPL-2", From 802bb3a7577334e48b269aaa75b0f887be2cbf7e Mon Sep 17 00:00:00 2001 From: Sparky Date: Sat, 23 Feb 2019 10:29:42 -0500 Subject: [PATCH 013/220] Make types more consistent There is no instance I can find where these values are ever *actually* strings. Changing them to boolean improves consistency. --- .../emby-webcomponents/browserdeviceprofile.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bower_components/emby-webcomponents/browserdeviceprofile.js b/src/bower_components/emby-webcomponents/browserdeviceprofile.js index 7b37a0cdb1..ad5237fde8 100644 --- a/src/bower_components/emby-webcomponents/browserdeviceprofile.js +++ b/src/bower_components/emby-webcomponents/browserdeviceprofile.js @@ -751,7 +751,7 @@ define(['browser'], function (browser) { Condition: 'Equals', Property: 'IsSecondaryAudio', Value: 'false', - IsRequired: 'false' + IsRequired: false }); } @@ -780,7 +780,7 @@ define(['browser'], function (browser) { Condition: 'Equals', Property: 'IsSecondaryAudio', Value: 'false', - IsRequired: 'false' + IsRequired: false } ] }); @@ -913,4 +913,4 @@ define(['browser'], function (browser) { return profile; }; -}); \ No newline at end of file +}); From 427c9d203685fbee2e7a92f8150f03bd9874a137 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 23 Feb 2019 16:38:53 +0000 Subject: [PATCH 014/220] deuglify and indent to 4 spaces site.js --- src/scripts/site.js | 1863 +++++++++++++++++++++++++++++-------------- 1 file changed, 1251 insertions(+), 612 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 573464ec2c..64b254ba13 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1,225 +1,337 @@ function getWindowLocationSearch(win) { "use strict"; + var search = (win || window).location.search; + if (!search) { - var index = window.location.href.indexOf("?"); - 1 != index && (search = window.location.href.substring(index)) + var index = window.location.href.indexOf("?"); + + if (-1 != index) { + search = window.location.href.substring(index); + } } - return search || "" + + return search || ""; } function getParameterByName(name, url) { "use strict"; + name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); - var regexS = "[\\?&]" + name + "=([^&#]*)", - regex = new RegExp(regexS, "i"), - results = regex.exec(url || getWindowLocationSearch()); - return null == results ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")) + var regexS = "[\\?&]" + name + "=([^&#]*)"; + var regex = new RegExp(regexS, "i"); + var results = regex.exec(url || getWindowLocationSearch()); + + if (null == results) { + return ""; + } + + return decodeURIComponent(results[1].replace(/\+/g, " ")); } function pageClassOn(eventName, className, fn) { "use strict"; - document.addEventListener(eventName, function(e) { - var target = e.target; - target.classList.contains(className) && fn.call(target, e) - }) + + document.addEventListener(eventName, function (e__q) { + var target = e__q.target; + + if (target.classList.contains(className)) { + fn.call(target, e__q); + } + }); } function pageIdOn(eventName, id, fn) { "use strict"; - document.addEventListener(eventName, function(e) { - var target = e.target; - target.id === id && fn.call(target, e) - }) + + document.addEventListener(eventName, function (e__w) { + var target = e__w.target; + + if (target.id === id) { + fn.call(target, e__w); + } + }); } + var Dashboard = { - allowPluginPages: function(pluginId) { - return true; - }, - getCurrentUser: function() { - return window.ApiClient.getCurrentUser(!1) - }, - serverAddress: function() { - if (AppInfo.isNativeApp) { - var apiClient = window.ApiClient; - return apiClient ? apiClient.serverAddress() : null - } - var urlLower = window.location.href.toLowerCase(), - index = urlLower.lastIndexOf("/web"); - if (-1 != index) return urlLower.substring(0, index); - var loc = window.location, - address = loc.protocol + "//" + loc.hostname; - return loc.port && (address += ":" + loc.port), address - }, - getCurrentUserId: function() { + allowPluginPages: function (pluginId) { + return true; + }, + getCurrentUser: function () { + return window.ApiClient.getCurrentUser(false); + }, + serverAddress: function () { + if (AppInfo.isNativeApp) { var apiClient = window.ApiClient; - return apiClient ? apiClient.getCurrentUserId() : null - }, - onServerChanged: function(userId, accessToken, apiClient) { - apiClient = apiClient || window.ApiClient, window.ApiClient = apiClient - }, - logout: function() { - ConnectionManager.logout().then(function() { - var loginPage; - if (AppInfo.isNativeApp) { - loginPage = "selectserver.html"; - window.ApiClient = null; - } else { - loginPage = "login.html"; - } - Dashboard.navigate(loginPage); - }) - }, - getConfigurationPageUrl: function(name) { - return "configurationpage?name=" + encodeURIComponent(name) - }, - getConfigurationResourceUrl: function(name) { - return AppInfo.isNativeApp ? ApiClient.getUrl("web/ConfigurationPage", { + + if (apiClient) { + return apiClient.serverAddress(); + } + + return null; + } + + var urlLower = window.location.href.toLowerCase(); + var index = urlLower.lastIndexOf("/web"); + + if (-1 != index) { + return urlLower.substring(0, index); + } + + var loc = window.location; + var address = loc.protocol + "//" + loc.hostname; + + if (loc.port) { + address += ":" + loc.port; + } + + return address; + }, + getCurrentUserId: function () { + var apiClient = window.ApiClient; + + if (apiClient) { + return apiClient.getCurrentUserId(); + } + + return null; + }, + onServerChanged: function (userId, accessToken, apiClient) { + apiClient = apiClient || window.ApiClient; + window.ApiClient = apiClient; + }, + logout: function () { + ConnectionManager.logout().then(function () { + var loginPage; + + if (AppInfo.isNativeApp) { + loginPage = "selectserver.html"; + window.ApiClient = null; + } else { + loginPage = "login.html"; + } + + Dashboard.navigate(loginPage); + }); + }, + getConfigurationPageUrl: function (name) { + return "configurationpage?name=" + encodeURIComponent(name); + }, + getConfigurationResourceUrl: function (name) { + if (AppInfo.isNativeApp) { + return ApiClient.getUrl("web/ConfigurationPage", { name: name - }) : Dashboard.getConfigurationPageUrl(name) - }, - navigate: function(url, preserveQueryString) { - if (!url) throw new Error("url cannot be null or empty"); - var queryString = getWindowLocationSearch(); - return preserveQueryString && queryString && (url += queryString), new Promise(function(resolve, reject) { - require(["appRouter"], function(appRouter) { - return appRouter.show(url).then(resolve, reject) - }) - }) - }, - navigate_direct: function(path) { - return new Promise(function(resolve, reject) { - require(["appRouter"], function(appRouter) { - return appRouter.showDirect(path).then(resolve, reject) - }) - }) - }, - processPluginConfigurationUpdateResult: function() { - require(["loading", "toast"], function(loading, toast) { - loading.hide(), toast(Globalize.translate("MessageSettingsSaved")) - }) - }, - processServerConfigurationUpdateResult: function(result) { - require(["loading", "toast"], function(loading, toast) { - loading.hide(), toast(Globalize.translate("MessageSettingsSaved")) - }) - }, - processErrorResponse: function(response) { - require(["loading"], function(loading) { - loading.hide() }); - var status = "" + response.status; - response.statusText && (status = response.statusText), Dashboard.alert({ - title: status, - message: response.headers ? response.headers.get("X-Application-Error-Code") : null - }) - }, - alert: function(options) { - if ("string" == typeof options) return void require(["toast"], function(toast) { + } + + return Dashboard.getConfigurationPageUrl(name); + }, + navigate: function (url, preserveQueryString) { + if (!url) { + throw new Error("url cannot be null or empty"); + } + + var queryString = getWindowLocationSearch(); + + if (preserveQueryString && queryString) { + url += queryString; + } + + return new Promise(function (resolve, reject) { + require(["appRouter"], function (appRouter) { + return appRouter.show(url).then(resolve, reject); + }); + }); + }, + navigate_direct: function (path) { + return new Promise(function (resolve, reject) { + require(["appRouter"], function (appRouter) { + return appRouter.showDirect(path).then(resolve, reject); + }); + }); + }, + processPluginConfigurationUpdateResult: function () { + require(["loading", "toast"], function (loading, toast) { + loading.hide(); + toast(Globalize.translate("MessageSettingsSaved")); + }); + }, + processServerConfigurationUpdateResult: function (result) { + require(["loading", "toast"], function (loading, toast) { + loading.hide(); + toast(Globalize.translate("MessageSettingsSaved")); + }); + }, + processErrorResponse: function (response) { + require(["loading"], function (loading) { + loading.hide(); + }); + + var status = "" + response.status; + + if (response.statusText) { + status = response.statusText; + } + + Dashboard.alert({ + title: status, + message: response.headers ? response.headers.get("X-Application-Error-Code") : null + }); + }, + alert: function (options) { + if ("string" == typeof options) { + return void require(["toast"], function (toast) { toast({ text: options - }) + }); }); - require(["alert"], function(alert) { - alert({ - title: options.title || Globalize.translate("HeaderAlert"), - text: options.message - }).then(options.callback || function() {}) - }) - }, - restartServer: function() { - var apiClient = window.ApiClient; - apiClient && require(["serverRestartDialog", "events"], function(ServerRestartDialog, events) { + } + + require(["alert"], function (alert) { + alert({ + title: options.title || Globalize.translate("HeaderAlert"), + text: options.message + }).then(options.callback || function () {}); + }); + }, + restartServer: function () { + var apiClient = window.ApiClient; + + if (apiClient) { + require(["serverRestartDialog", "events"], function (ServerRestartDialog, events) { var dialog = new ServerRestartDialog({ apiClient: apiClient }); - events.on(dialog, "restarted", function() { - AppInfo.isNativeApp ? apiClient.ensureWebSocket() : window.location.reload(!0) - }), dialog.show() - }) - }, - capabilities: function(appHost) { - var caps = { - PlayableMediaTypes: ["Audio", "Video"], - SupportedCommands: ["MoveUp", "MoveDown", "MoveLeft", "MoveRight", "PageUp", "PageDown", "PreviousLetter", "NextLetter", "ToggleOsd", "ToggleContextMenu", "Select", "Back", "SendKey", "SendString", "GoHome", "GoToSettings", "VolumeUp", "VolumeDown", "Mute", "Unmute", "ToggleMute", "SetVolume", "SetAudioStreamIndex", "SetSubtitleStreamIndex", "DisplayContent", "GoToSearch", "DisplayMessage", "SetRepeatMode", "ChannelUp", "ChannelDown", "PlayMediaSource", "PlayTrailers"], - SupportsPersistentIdentifier: "cordova" === self.appMode || "android" === self.appMode, - SupportsMediaControl: !0 - }; - caps.IconUrl = appHost.deviceIconUrl(), caps.SupportsSync = appHost.supports("sync"), caps.SupportsContentUploading = appHost.supports("cameraupload"); - appHost.getPushTokenInfo(); - return caps = Object.assign(caps, appHost.getPushTokenInfo()) + events.on(dialog, "restarted", function () { + if (AppInfo.isNativeApp) { + apiClient.ensureWebSocket(); + } else { + window.location.reload(true); + } + }); + dialog.show(); + }); } }, - AppInfo = {}; -! function() { + capabilities: function (appHost) { + var caps = { + PlayableMediaTypes: ["Audio", "Video"], + SupportedCommands: ["MoveUp", "MoveDown", "MoveLeft", "MoveRight", "PageUp", "PageDown", "PreviousLetter", "NextLetter", "ToggleOsd", "ToggleContextMenu", "Select", "Back", "SendKey", "SendString", "GoHome", "GoToSettings", "VolumeUp", "VolumeDown", "Mute", "Unmute", "ToggleMute", "SetVolume", "SetAudioStreamIndex", "SetSubtitleStreamIndex", "DisplayContent", "GoToSearch", "DisplayMessage", "SetRepeatMode", "ChannelUp", "ChannelDown", "PlayMediaSource", "PlayTrailers"], + SupportsPersistentIdentifier: "cordova" === self.appMode || "android" === self.appMode, + SupportsMediaControl: true + }; + caps.IconUrl = appHost.deviceIconUrl(); + caps.SupportsSync = appHost.supports("sync"); + caps.SupportsContentUploading = appHost.supports("cameraupload"); + appHost.getPushTokenInfo(); + return caps = Object.assign(caps, appHost.getPushTokenInfo()); + } +}; +var AppInfo = {}; +!function () { "use strict"; function initializeApiClient(apiClient) { - "cordova" !== self.appMode && "android" !== self.appMode || (apiClient.getAvailablePlugins = function() { - return Promise.resolve([]) - }) + if (!("cordova" !== self.appMode && "android" !== self.appMode)) { + apiClient.getAvailablePlugins = function () { + return Promise.resolve([]); + }; + } } - function onApiClientCreated(e, newApiClient) { - initializeApiClient(newApiClient), window.$ && ($.ajax = newApiClient.ajax) + function onApiClientCreated(e__e, newApiClient) { + initializeApiClient(newApiClient); + + if (window.$) { + $.ajax = newApiClient.ajax; + } } function defineConnectionManager(connectionManager) { - window.ConnectionManager = connectionManager, define("connectionManager", [], function() { - return connectionManager - }) + window.ConnectionManager = connectionManager; + define("connectionManager", [], function () { + return connectionManager; + }); } function bindConnectionManagerEvents(connectionManager, events, userSettings) { - window.Events = events, events.on(ConnectionManager, "apiclientcreated", onApiClientCreated), connectionManager.currentApiClient = function() { + window.Events = events; + events.on(ConnectionManager, "apiclientcreated", onApiClientCreated); + + connectionManager.currentApiClient = function () { if (!localApiClient) { var server = connectionManager.getLastUsedServer(); - server && (localApiClient = connectionManager.getApiClient(server.Id)) + + if (server) { + localApiClient = connectionManager.getApiClient(server.Id); + } } - return localApiClient - }, connectionManager.onLocalUserSignedIn = function(user) { - return localApiClient = connectionManager.getApiClient(user.ServerId), window.ApiClient = localApiClient, userSettings.setUserInfo(user.Id, localApiClient) - }, events.on(connectionManager, "localusersignedout", function() { - userSettings.setUserInfo(null, null) - }) + + return localApiClient; + }; + + connectionManager.onLocalUserSignedIn = function (user) { + localApiClient = connectionManager.getApiClient(user.ServerId); + window.ApiClient = localApiClient; + return userSettings.setUserInfo(user.Id, localApiClient); + }; + + events.on(connectionManager, "localusersignedout", function () { + userSettings.setUserInfo(null, null); + }); } function createConnectionManager() { - return new Promise(function(resolve, reject) { - require(["connectionManagerFactory", "apphost", "credentialprovider", "events", "userSettings"], function(ConnectionManager, apphost, credentialProvider, events, userSettings) { - var credentialProviderInstance = new credentialProvider; + return new Promise(function (resolve, reject) { + require(["connectionManagerFactory", "apphost", "credentialprovider", "events", "userSettings"], function (ConnectionManager, apphost, credentialProvider, events, userSettings) { + var credentialProviderInstance = new credentialProvider(); var promises = [apphost.getSyncProfile(), apphost.init()]; - Promise.all(promises).then(function(responses) { - var deviceProfile = responses[0], - capabilities = Dashboard.capabilities(apphost); + Promise.all(promises).then(function (responses) { + var deviceProfile = responses[0]; + var capabilities = Dashboard.capabilities(apphost); capabilities.DeviceProfile = deviceProfile; var connectionManager = new ConnectionManager(credentialProviderInstance, apphost.appName(), apphost.appVersion(), apphost.deviceName(), apphost.deviceId(), capabilities, window.devicePixelRatio); - if (defineConnectionManager(connectionManager), bindConnectionManagerEvents(connectionManager, events, userSettings), !AppInfo.isNativeApp) return console.log("loading ApiClient singleton"), getRequirePromise(["apiclient"]).then(function(apiClientFactory) { - console.log("creating ApiClient singleton"); - var apiClient = new apiClientFactory(Dashboard.serverAddress(), apphost.appName(), apphost.appVersion(), apphost.deviceName(), apphost.deviceId(), window.devicePixelRatio); - apiClient.enableAutomaticNetworking = !1, apiClient.manualAddressOnly = !0, connectionManager.addApiClient(apiClient), window.ApiClient = apiClient, localApiClient = apiClient, console.log("loaded ApiClient singleton"), resolve() - }); - resolve() + + if (defineConnectionManager(connectionManager), bindConnectionManagerEvents(connectionManager, events, userSettings), !AppInfo.isNativeApp) { + console.log("loading ApiClient singleton"); + return getRequirePromise(["apiclient"]).then(function (apiClientFactory) { + console.log("creating ApiClient singleton"); + var apiClient = new apiClientFactory(Dashboard.serverAddress(), apphost.appName(), apphost.appVersion(), apphost.deviceName(), apphost.deviceId(), window.devicePixelRatio); + apiClient.enableAutomaticNetworking = false; + apiClient.manualAddressOnly = true; + connectionManager.addApiClient(apiClient); + window.ApiClient = apiClient; + localApiClient = apiClient; + console.log("loaded ApiClient singleton"); + resolve(); + }); + } + + resolve(); }); }); }); } function returnFirstDependency(obj) { - return obj + return obj; } function getSettingsBuilder(UserSettings, layoutManager, browser) { - UserSettings.prototype.enableThemeVideos = function(val) { + UserSettings.prototype.enableThemeVideos = function (val) { if (val != null) { return this.set('enableThemeVideos', val.toString(), false); } + val = this.get('enableThemeVideos', false); + if (val !== 'false') { return !layoutManager.mobile; } else { return !browser.slow; } }; + return UserSettings; } @@ -228,7 +340,7 @@ var Dashboard = { } function getPlaybackManager(playbackManager) { - window.addEventListener("beforeunload", function(e) { + window.addEventListener("beforeunload", function (e__r) { try { playbackManager.onAppClose(); } catch (err) { @@ -242,6 +354,7 @@ var Dashboard = { if (appHost.getDefaultLayout) { layoutManager.defaultLayout = appHost.getDefaultLayout(); } + layoutManager.init(); return layoutManager; } @@ -265,26 +378,34 @@ var Dashboard = { function getCastSenderApiLoader() { var ccLoaded = false; return { - load: function() { - return ccLoaded ? Promise.resolve() : new Promise(function(resolve, reject) { + load: function () { + if (ccLoaded) { + return Promise.resolve(); + } + + return new Promise(function (resolve, reject) { var fileref = document.createElement("script"); fileref.setAttribute("type", "text/javascript"); - fileref.onload = function() { - ccLoaded = !0, resolve() + + fileref.onload = function () { + ccLoaded = true; + resolve(); }; + fileref.setAttribute("src", "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js"); document.querySelector("head").appendChild(fileref); - }) + }); } - } + }; } function getDummyCastSenderApiLoader() { return { - load: function() { - return window.chrome = window.chrome || {}, Promise.resolve() + load: function () { + window.chrome = window.chrome || {}; + return Promise.resolve(); } - } + }; } function createSharedAppFooter(appFooter) { @@ -296,9 +417,13 @@ var Dashboard = { } function defineResizeObserver() { - self.ResizeObserver ? define("ResizeObserver", [], function() { - return self.ResizeObserver - }) : define("ResizeObserver", ["bower_components/emby-webcomponents/resize-observer-polyfill/ResizeObserver"], returnFirstDependency) + if (self.ResizeObserver) { + define("ResizeObserver", [], function () { + return self.ResizeObserver; + }); + } else { + define("ResizeObserver", ["bower_components/emby-webcomponents/resize-observer-polyfill/ResizeObserver"], returnFirstDependency); + } } function initRequireWithBrowser(browser) { @@ -306,93 +431,183 @@ var Dashboard = { var apiClientBowerPath = bowerPath + "/emby-apiclient"; var embyWebComponentsBowerPath = bowerPath + "/emby-webcomponents"; - "android" === self.appMode - ? define("filesystem", ["cordova/filesystem"], returnFirstDependency) - : define("filesystem", [embyWebComponentsBowerPath + "/filesystem"], returnFirstDependency); - window.IntersectionObserver && !browser.edge - ? define("lazyLoader", [embyWebComponentsBowerPath + "/lazyloader/lazyloader-intersectionobserver"], returnFirstDependency) - : define("lazyLoader", [embyWebComponentsBowerPath + "/lazyloader/lazyloader-scroll"], returnFirstDependency); - "android" === self.appMode - ? define("shell", ["cordova/shell"], returnFirstDependency) - : define("shell", [embyWebComponentsBowerPath + "/shell"], returnFirstDependency); - "cordova" === self.appMode || "android" === self.appMode - ? (define("apiclientcore", ["bower_components/emby-apiclient/apiclient"], returnFirstDependency), define("apiclient", ["bower_components/emby-apiclient/apiclientex"], returnFirstDependency)) - : define("apiclient", ["bower_components/emby-apiclient/apiclient"], returnFirstDependency) + if ("android" === self.appMode) { + define("filesystem", ["cordova/filesystem"], returnFirstDependency); + } else { + define("filesystem", [embyWebComponentsBowerPath + "/filesystem"], returnFirstDependency); + } + + if (window.IntersectionObserver && !browser.edge) { + define("lazyLoader", [embyWebComponentsBowerPath + "/lazyloader/lazyloader-intersectionobserver"], returnFirstDependency); + } else { + define("lazyLoader", [embyWebComponentsBowerPath + "/lazyloader/lazyloader-scroll"], returnFirstDependency); + } + + if ("android" === self.appMode) { + define("shell", ["cordova/shell"], returnFirstDependency); + } else { + define("shell", [embyWebComponentsBowerPath + "/shell"], returnFirstDependency); + } + + if ("cordova" === self.appMode || "android" === self.appMode) { + define("apiclientcore", ["bower_components/emby-apiclient/apiclient"], returnFirstDependency); + define("apiclient", ["bower_components/emby-apiclient/apiclientex"], returnFirstDependency); + } else { + define("apiclient", ["bower_components/emby-apiclient/apiclient"], returnFirstDependency); + } + define("actionsheet", ["webActionSheet"], returnFirstDependency); - "registerElement" in document - ? define("registerElement", []) - : browser.msie - ? define("registerElement", [bowerPath + "/webcomponentsjs/webcomponents-lite.min.js"], returnFirstDependency) - : define("registerElement", [bowerPath + "/document-register-element/build/document-register-element"], returnFirstDependency); - "cordova" === self.appMode || "android" === self.appMode - ? define("serverdiscovery", ["cordova/serverdiscovery"], returnFirstDependency) - : define("serverdiscovery", [apiClientBowerPath + "/serverdiscovery"], returnFirstDependency); - "cordova" === self.appMode && browser.iOSVersion && browser.iOSVersion < 11 - ? define("imageFetcher", ["cordova/imagestore"], returnFirstDependency) - : define("imageFetcher", [embyWebComponentsBowerPath + "/images/basicimagefetcher"], returnFirstDependency); + + if ("registerElement" in document) { + define("registerElement", []); + } else { + if (browser.msie) { + define("registerElement", [bowerPath + "/webcomponentsjs/webcomponents-lite.min.js"], returnFirstDependency); + } else { + define("registerElement", [bowerPath + "/document-register-element/build/document-register-element"], returnFirstDependency); + } + } + + if ("cordova" === self.appMode || "android" === self.appMode) { + define("serverdiscovery", ["cordova/serverdiscovery"], returnFirstDependency); + } else { + define("serverdiscovery", [apiClientBowerPath + "/serverdiscovery"], returnFirstDependency); + } + + if ("cordova" === self.appMode && browser.iOSVersion && browser.iOSVersion < 11) { + define("imageFetcher", ["cordova/imagestore"], returnFirstDependency); + } else { + define("imageFetcher", [embyWebComponentsBowerPath + "/images/basicimagefetcher"], returnFirstDependency); + } var preferNativeAlerts = browser.tv; - preferNativeAlerts && window.alert - ? define("alert", [embyWebComponentsBowerPath + "/alert/nativealert"], returnFirstDependency) - : define("alert", [embyWebComponentsBowerPath + "/alert/alert"], returnFirstDependency); + + if (preferNativeAlerts && window.alert) { + define("alert", [embyWebComponentsBowerPath + "/alert/nativealert"], returnFirstDependency); + } else { + define("alert", [embyWebComponentsBowerPath + "/alert/alert"], returnFirstDependency); + } + defineResizeObserver(); define("dialog", [embyWebComponentsBowerPath + "/dialog/dialog"], returnFirstDependency); - preferNativeAlerts && window.confirm - ? define("confirm", [embyWebComponentsBowerPath + "/confirm/nativeconfirm"], returnFirstDependency) - : define("confirm", [embyWebComponentsBowerPath + "/confirm/confirm"], returnFirstDependency); - (preferNativeAlerts || browser.xboxOne) && window.confirm - ? define("prompt", [embyWebComponentsBowerPath + "/prompt/nativeprompt"], returnFirstDependency) - : define("prompt", [embyWebComponentsBowerPath + "/prompt/prompt"], returnFirstDependency); - browser.tizen || browser.operaTv || browser.chromecast || browser.orsay || browser.web0s || browser.ps4 - ? define("loading", [embyWebComponentsBowerPath + "/loading/loading-legacy"], returnFirstDependency) - : define("loading", [embyWebComponentsBowerPath + "/loading/loading-lite"], returnFirstDependency); + + if (preferNativeAlerts && window.confirm) { + define("confirm", [embyWebComponentsBowerPath + "/confirm/nativeconfirm"], returnFirstDependency); + } else { + define("confirm", [embyWebComponentsBowerPath + "/confirm/confirm"], returnFirstDependency); + } + + if ((preferNativeAlerts || browser.xboxOne) && window.confirm) { + define("prompt", [embyWebComponentsBowerPath + "/prompt/nativeprompt"], returnFirstDependency); + } else { + define("prompt", [embyWebComponentsBowerPath + "/prompt/prompt"], returnFirstDependency); + } + + if (browser.tizen || browser.operaTv || browser.chromecast || browser.orsay || browser.web0s || browser.ps4) { + define("loading", [embyWebComponentsBowerPath + "/loading/loading-legacy"], returnFirstDependency); + } else { + define("loading", [embyWebComponentsBowerPath + "/loading/loading-lite"], returnFirstDependency); + } + define("multi-download", [embyWebComponentsBowerPath + "/multidownload"], returnFirstDependency); - "android" === self.appMode - ? define("fileDownloader", ["cordova/filedownloader"], returnFirstDependency) - : define("fileDownloader", [embyWebComponentsBowerPath + "/filedownloader"], returnFirstDependency); + + if ("android" === self.appMode) { + define("fileDownloader", ["cordova/filedownloader"], returnFirstDependency); + } else { + define("fileDownloader", [embyWebComponentsBowerPath + "/filedownloader"], returnFirstDependency); + } + define("localassetmanager", [apiClientBowerPath + "/localassetmanager"], returnFirstDependency); - "cordova" === self.appMode || "android" === self.appMode - ? define("castSenderApiLoader", [], getDummyCastSenderApiLoader) - : define("castSenderApiLoader", [], getCastSenderApiLoader); - self.Windows - ? (define("bgtaskregister", ["environments/windows-uwp/bgtaskregister"], returnFirstDependency), define("transfermanager", ["environments/windows-uwp/transfermanager"], returnFirstDependency), define("filerepository", ["environments/windows-uwp/filerepository"], returnFirstDependency)) - : "cordova" === self.appMode - ? (define("filerepository", ["cordova/filerepository"], returnFirstDependency), define("transfermanager", ["filerepository"], returnFirstDependency)) - : "android" === self.appMode - ? (define("transfermanager", ["cordova/transfermanager"], returnFirstDependency), define("filerepository", ["cordova/filerepository"], returnFirstDependency)) - : (define("transfermanager", [apiClientBowerPath + "/sync/transfermanager"], returnFirstDependency), define("filerepository", [apiClientBowerPath + "/sync/filerepository"], returnFirstDependency)); - "android" === self.appMode - ? define("localsync", ["cordova/localsync"], returnFirstDependency) - : define("localsync", [apiClientBowerPath + "/sync/localsync"], returnFirstDependency); + + if ("cordova" === self.appMode || "android" === self.appMode) { + define("castSenderApiLoader", [], getDummyCastSenderApiLoader); + } else { + define("castSenderApiLoader", [], getCastSenderApiLoader); + } + + if (self.Windows) { + define("bgtaskregister", ["environments/windows-uwp/bgtaskregister"], returnFirstDependency); + define("transfermanager", ["environments/windows-uwp/transfermanager"], returnFirstDependency); + define("filerepository", ["environments/windows-uwp/filerepository"], returnFirstDependency); + } else { + if ("cordova" === self.appMode) { + define("filerepository", ["cordova/filerepository"], returnFirstDependency); + define("transfermanager", ["filerepository"], returnFirstDependency); + } else { + if ("android" === self.appMode) { + define("transfermanager", ["cordova/transfermanager"], returnFirstDependency); + define("filerepository", ["cordova/filerepository"], returnFirstDependency); + } else { + define("transfermanager", [apiClientBowerPath + "/sync/transfermanager"], returnFirstDependency); + define("filerepository", [apiClientBowerPath + "/sync/filerepository"], returnFirstDependency); + } + } + } + + if ("android" === self.appMode) { + define("localsync", ["cordova/localsync"], returnFirstDependency); + } else { + define("localsync", [apiClientBowerPath + "/sync/localsync"], returnFirstDependency); + } } function getRequirePromise(deps) { - return new Promise(function(resolve, reject) { - require(deps, resolve) - }) + return new Promise(function (resolve, reject) { + require(deps, resolve); + }); } function init() { - "android" === self.appMode && define("nativedirectorychooser", ["cordova/nativedirectorychooser"], returnFirstDependency), define("livetvcss", ["css!css/livetv.css"], returnFirstDependency), define("detailtablecss", ["css!css/detailtable.css"], returnFirstDependency), define("buttonenabled", ["legacy/buttonenabled"], returnFirstDependency); + if ("android" === self.appMode) { + define("nativedirectorychooser", ["cordova/nativedirectorychooser"], returnFirstDependency); + } + + define("livetvcss", ["css!css/livetv.css"], returnFirstDependency); + define("detailtablecss", ["css!css/detailtable.css"], returnFirstDependency); + define("buttonenabled", ["legacy/buttonenabled"], returnFirstDependency); var list = []; - window.fetch || list.push("fetch"), "function" != typeof Object.assign && list.push("objectassign"), Array.prototype.filter || list.push("arraypolyfills"), Function.prototype.bind || list.push("functionbind"), window.requestAnimationFrame || list.push("raf"), require(list, function() { - createConnectionManager().then(function() { - console.log("initAfterDependencies promises resolved"), require(["globalize", "browser"], function(globalize, browser) { - window.Globalize = globalize, loadCoreDictionary(globalize).then(function() { - onGlobalizeInit(browser) - }) - }) - }) - }) + + if (!window.fetch) { + list.push("fetch"); + } + + if ("function" != typeof Object.assign) { + list.push("objectassign"); + } + + if (!Array.prototype.filter) { + list.push("arraypolyfills"); + } + + if (!Function.prototype.bind) { + list.push("functionbind"); + } + + if (!window.requestAnimationFrame) { + list.push("raf"); + } + + require(list, function () { + createConnectionManager().then(function () { + console.log("initAfterDependencies promises resolved"); + + require(["globalize", "browser"], function (globalize, browser) { + window.Globalize = globalize; + loadCoreDictionary(globalize).then(function () { + onGlobalizeInit(browser); + }); + }); + }); + }); } function loadCoreDictionary(globalize) { var languages = ["ar", "be-by", "bg-bg", "ca", "cs", "da", "de", "el", "en-gb", "en-us", "es", "es-ar", "es-mx", "fa", "fi", "fr", "fr-ca", "gsw", "he", "hi-in", "hr", "hu", "id", "it", "kk", "ko", "lt-lt", "ms", "nb", "nl", "pl", "pt-br", "pt-pt", "ro", "ru", "sk", "sl-si", "sv", "tr", "uk", "vi", "zh-cn", "zh-hk", "zh-tw"]; - var translations = languages.map(function(i) { + var translations = languages.map(function (i__t) { return { - lang: i, - path: "strings/" + i + ".json" - } + lang: i__t, + path: "strings/" + i__t + ".json" + }; }); globalize.defaultModule("core"); return globalize.loadStrings({ @@ -403,21 +618,34 @@ var Dashboard = { function onGlobalizeInit(browser) { if ("android" === self.appMode) { - if (-1 !== self.location.href.toString().toLowerCase().indexOf("start=backgroundsync")) return onAppReady(browser) + if (-1 !== self.location.href.toString().toLowerCase().indexOf("start=backgroundsync")) { + return onAppReady(browser); + } } + document.title = Globalize.translateDocument(document.title, "core"); var deps = ["apphost"]; - browser.tv && !browser.android ? (console.log("Using system fonts with explicit sizes"), deps.push("systemFontsSizedCss")) : (console.log("Using default fonts"), deps.push("systemFontsCss")), deps.push("css!css/librarybrowser"), require(deps, function(appHost) { - loadPlugins([], appHost, browser).then(function() { + + if (browser.tv && !browser.android) { + console.log("Using system fonts with explicit sizes"); + deps.push("systemFontsSizedCss"); + } else { + console.log("Using default fonts"); + deps.push("systemFontsCss"); + } + + deps.push("css!css/librarybrowser"); + + require(deps, function (appHost) { + loadPlugins([], appHost, browser).then(function () { onAppReady(browser); - }) - }) + }); + }); } function defineRoute(newRoute, dictionary) { var baseRoute = Emby.Page.baseUrl(); var path = newRoute.path; - path = path.replace(baseRoute, ""); console.log("Defining route: " + path); newRoute.dictionary = newRoute.dictionary || dictionary || "core"; @@ -429,586 +657,765 @@ var Dashboard = { defineRoute({ path: "/addplugin.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin", controller: "scripts/addpluginpage" - }), defineRoute({ + }); + defineRoute({ path: "/appservices.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/autoorganizelog.html", dependencies: [], roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/channelsettings.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/addserver.html", dependencies: ["emby-button", "emby-input"], - autoFocus: !1, - anonymous: !0, - startup: !0, + autoFocus: false, + anonymous: true, + startup: true, controller: "scripts/addserver" - }), defineRoute({ + }); + defineRoute({ path: "/dashboard.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin", controller: "scripts/dashboardpage" - }), defineRoute({ + }); + defineRoute({ path: "/dashboardgeneral.html", controller: "dashboard/dashboardgeneral", - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/dashboardhosting.html", dependencies: ["emby-input", "emby-button"], - autoFocus: !1, + autoFocus: false, roles: "admin", controller: "dashboard/dashboardhosting" - }), defineRoute({ + }); + defineRoute({ path: "/devices/devices.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin", controller: "devices/devices" - }), defineRoute({ + }); + defineRoute({ path: "/devices/device.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin", controller: "devices/device" - }), defineRoute({ + }); + defineRoute({ path: "/dlnaprofile.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/dlnaprofiles.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/dlnaserversettings.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/dlnasettings.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/edititemmetadata.html", dependencies: [], controller: "scripts/edititemmetadata", - autoFocus: !1 - }), defineRoute({ + autoFocus: false + }); + defineRoute({ path: "/encodingsettings.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/opensubtitles.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/forgotpassword.html", dependencies: ["emby-input", "emby-button"], - anonymous: !0, - startup: !0, + anonymous: true, + startup: true, controller: "scripts/forgotpassword" - }), defineRoute({ + }); + defineRoute({ path: "/forgotpasswordpin.html", dependencies: ["emby-input", "emby-button"], - autoFocus: !1, - anonymous: !0, - startup: !0, + autoFocus: false, + anonymous: true, + startup: true, controller: "scripts/forgotpasswordpin" - }), defineRoute({ + }); + defineRoute({ path: "/home.html", dependencies: [], - autoFocus: !1, + autoFocus: false, controller: "home/home", transition: "fade", type: "home" - }), defineRoute({ + }); + defineRoute({ path: "/list/list.html", dependencies: [], - autoFocus: !1, + autoFocus: false, controller: "list/list", transition: "fade" - }), defineRoute({ + }); + defineRoute({ path: "/index.html", dependencies: [], - autoFocus: !1, - isDefaultRoute: !0 - }), defineRoute({ + autoFocus: false, + isDefaultRoute: true + }); + defineRoute({ path: "/itemdetails.html", dependencies: ["emby-button", "scripts/livetvcomponents", "paper-icon-button-light", "emby-itemscontainer"], controller: "scripts/itemdetailpage", - autoFocus: !1, + autoFocus: false, transition: "fade" - }), defineRoute({ + }); + defineRoute({ path: "/library.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/librarydisplay.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin", controller: "dashboard/librarydisplay" - }), defineRoute({ + }); + defineRoute({ path: "/librarysettings.html", dependencies: ["emby-collapse", "emby-input", "emby-button", "emby-select"], - autoFocus: !1, + autoFocus: false, roles: "admin", controller: "dashboard/librarysettings" - }), defineRoute({ + }); + defineRoute({ path: "/livetv.html", dependencies: ["emby-button", "livetvcss"], controller: "scripts/livetvsuggested", - autoFocus: !1, + autoFocus: false, transition: "fade" - }), defineRoute({ + }); + defineRoute({ path: "/livetvguideprovider.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/livetvseriestimer.html", dependencies: ["emby-checkbox", "emby-input", "emby-button", "emby-collapse", "scripts/livetvcomponents", "scripts/livetvseriestimer", "livetvcss"], - autoFocus: !1, + autoFocus: false, controller: "scripts/livetvseriestimer" - }), defineRoute({ + }); + defineRoute({ path: "/livetvsettings.html", dependencies: [], - autoFocus: !1 - }), defineRoute({ + autoFocus: false + }); + defineRoute({ path: "/livetvstatus.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/livetvtuner.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin", controller: "dashboard/livetvtuner" - }), defineRoute({ + }); + defineRoute({ path: "/log.html", dependencies: ["emby-checkbox"], roles: "admin", controller: "dashboard/logpage" - }), defineRoute({ + }); + defineRoute({ path: "/login.html", dependencies: ["emby-button", "emby-input"], - autoFocus: !1, - anonymous: !0, - startup: !0, + autoFocus: false, + anonymous: true, + startup: true, controller: "scripts/loginpage" - }), defineRoute({ + }); + defineRoute({ path: "/metadataadvanced.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/metadataimages.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/metadatanfo.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/movies.html", dependencies: ["emby-button"], - autoFocus: !1, + autoFocus: false, controller: "scripts/moviesrecommended", transition: "fade" - }), defineRoute({ + }); + defineRoute({ path: "/music.html", dependencies: [], controller: "scripts/musicrecommended", - autoFocus: !1, + autoFocus: false, transition: "fade" - }), defineRoute({ + }); + defineRoute({ path: "/mypreferencesdisplay.html", dependencies: ["emby-checkbox", "emby-button", "emby-select"], - autoFocus: !1, + autoFocus: false, transition: "fade", controller: "scripts/mypreferencesdisplay" - }), defineRoute({ + }); + defineRoute({ path: "/mypreferenceshome.html", dependencies: [], - autoFocus: !1, + autoFocus: false, transition: "fade", controller: "scripts/mypreferenceshome" - }), defineRoute({ + }); + defineRoute({ path: "/mypreferencessubtitles.html", dependencies: [], - autoFocus: !1, + autoFocus: false, transition: "fade", controller: "scripts/mypreferencessubtitles" - }), defineRoute({ + }); + defineRoute({ path: "/mypreferenceslanguages.html", dependencies: ["emby-button", "emby-checkbox", "emby-select"], - autoFocus: !1, + autoFocus: false, transition: "fade", controller: "scripts/mypreferenceslanguages" - }), defineRoute({ + }); + defineRoute({ path: "/mypreferencesmenu.html", dependencies: ["emby-button"], - autoFocus: !1, + autoFocus: false, transition: "fade", controller: "scripts/mypreferencescommon" - }), defineRoute({ + }); + defineRoute({ path: "/myprofile.html", dependencies: ["emby-button", "emby-collapse", "emby-checkbox", "emby-input"], - autoFocus: !1, + autoFocus: false, transition: "fade", controller: "scripts/myprofile" - }), defineRoute({ + }); + defineRoute({ path: "/notificationsetting.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/notificationsettings.html", controller: "scripts/notificationsettings", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/nowplaying.html", dependencies: ["paper-icon-button-light", "emby-slider", "emby-button", "emby-input", "emby-itemscontainer"], controller: "scripts/nowplayingpage", - autoFocus: !1, + autoFocus: false, transition: "fade", - fullscreen: !0, - supportsThemeMedia: !0, - enableMediaControl: !1 - }), defineRoute({ + fullscreen: true, + supportsThemeMedia: true, + enableMediaControl: false + }); + defineRoute({ path: "/playbackconfiguration.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/plugincatalog.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin", controller: "scripts/plugincatalogpage" - }), defineRoute({ + }); + defineRoute({ path: "/plugins.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/scheduledtask.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin", controller: "scripts/scheduledtaskpage" - }), defineRoute({ + }); + defineRoute({ path: "/scheduledtasks.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin", controller: "scripts/scheduledtaskspage" - }), defineRoute({ + }); + defineRoute({ path: "/search.html", dependencies: [], controller: "scripts/searchpage" - }), defineRoute({ + }); + defineRoute({ path: "/selectserver.html", dependencies: ["listViewStyle", "emby-button"], - autoFocus: !1, - anonymous: !0, - startup: !0, + autoFocus: false, + anonymous: true, + startup: true, controller: "scripts/selectserver" - }), defineRoute({ + }); + defineRoute({ path: "/serveractivity.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin", controller: "dashboard/serveractivity" - }), defineRoute({ + }); + defineRoute({ path: "/serversecurity.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/streamingsettings.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/support.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/tv.html", dependencies: ["paper-icon-button-light", "emby-button"], - autoFocus: !1, + autoFocus: false, controller: "scripts/tvrecommended", transition: "fade" - }), defineRoute({ + }); + defineRoute({ path: "/useredit.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/userlibraryaccess.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/usernew.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/userparentalcontrol.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/userpassword.html", dependencies: ["emby-input", "emby-button", "emby-checkbox"], - autoFocus: !1, + autoFocus: false, controller: "scripts/userpasswordpage" - }), defineRoute({ + }); + defineRoute({ path: "/userprofiles.html", dependencies: [], - autoFocus: !1, + autoFocus: false, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/wizardremoteaccess.html", dependencies: ["dashboardcss"], - autoFocus: !1, - anonymous: !0, + autoFocus: false, + anonymous: true, controller: "dashboard/wizardremoteaccess" - }), defineRoute({ + }); + defineRoute({ path: "/wizardfinish.html", dependencies: ["emby-button", "dashboardcss"], - autoFocus: !1, - anonymous: !0, + autoFocus: false, + anonymous: true, controller: "dashboard/wizardfinishpage" - }), defineRoute({ + }); + defineRoute({ path: "/wizardlibrary.html", dependencies: ["dashboardcss"], - autoFocus: !1, - anonymous: !0 - }), defineRoute({ + autoFocus: false, + anonymous: true + }); + defineRoute({ path: "/wizardsettings.html", dependencies: ["dashboardcss"], - autoFocus: !1, - anonymous: !0, + autoFocus: false, + anonymous: true, controller: "dashboard/wizardsettings" - }), defineRoute({ + }); + defineRoute({ path: "/wizardstart.html", dependencies: ["dashboardcss"], - autoFocus: !1, - anonymous: !0, + autoFocus: false, + anonymous: true, controller: "dashboard/wizardstart" - }), defineRoute({ + }); + defineRoute({ path: "/wizarduser.html", dependencies: ["dashboardcss", "emby-input"], controller: "scripts/wizarduserpage", - autoFocus: !1, - anonymous: !0 - }), defineRoute({ + autoFocus: false, + anonymous: true + }); + defineRoute({ path: "/videoosd.html", dependencies: [], transition: "fade", controller: "scripts/videoosd", - autoFocus: !1, + autoFocus: false, type: "video-osd", - supportsThemeMedia: !0, - fullscreen: !0, - enableMediaControl: !1 - }), defineRoute({ + supportsThemeMedia: true, + fullscreen: true, + enableMediaControl: false + }); + defineRoute({ path: "/configurationpage", dependencies: [], - autoFocus: !1, - enableCache: !1, - enableContentQueryString: !0, + autoFocus: false, + enableCache: false, + enableContentQueryString: true, roles: "admin" - }), defineRoute({ + }); + defineRoute({ path: "/", - isDefaultRoute: !0, - autoFocus: !1, + isDefaultRoute: true, + autoFocus: false, dependencies: [] - }) + }); } function getPluginPageContentPath() { - return window.ApiClient ? ApiClient.getUrl("web/ConfigurationPage") : null + if (window.ApiClient) { + return ApiClient.getUrl("web/ConfigurationPage"); + } + + return null; } function loadPlugins(externalPlugins, appHost, browser, shell) { console.log("Loading installed plugins"); - var list = [ - "bower_components/emby-webcomponents/playback/playbackvalidation", - "bower_components/emby-webcomponents/playback/playaccessvalidation", - "bower_components/emby-webcomponents/playback/experimentalwarnings", - "bower_components/emby-webcomponents/htmlaudioplayer/plugin", - "bower_components/emby-webcomponents/htmlvideoplayer/plugin", - "bower_components/emby-webcomponents/photoplayer/plugin", - "bower_components/emby-webcomponents/youtubeplayer/plugin" - ]; + var list = ["bower_components/emby-webcomponents/playback/playbackvalidation", "bower_components/emby-webcomponents/playback/playaccessvalidation", "bower_components/emby-webcomponents/playback/experimentalwarnings", "bower_components/emby-webcomponents/htmlaudioplayer/plugin", "bower_components/emby-webcomponents/htmlvideoplayer/plugin", "bower_components/emby-webcomponents/photoplayer/plugin", "bower_components/emby-webcomponents/youtubeplayer/plugin"]; + if ("cordova" === self.appMode) { list.push("cordova/chromecast"); } + if ("android" === self.appMode) { list.push("cordova/externalplayer"); } + if (appHost.supports("remotecontrol")) { list.push("bower_components/emby-webcomponents/sessionplayer"); + if (browser.chrome || browser.opera) { list.push("bower_components/emby-webcomponents/chromecast/chromecastplayer"); } } - for (var i = 0, length = externalPlugins.length; i < length; i++) list.push(externalPlugins[i]); - return new Promise(function(resolve, reject) { - Promise.all(list.map(loadPlugin)).then(function() { - require(["packageManager"], function(packageManager) { - packageManager.init().then(resolve, reject) - }) - }, reject) - }) + + for (var i__y = 0, length = externalPlugins.length; i__y < length; i__y++) { + list.push(externalPlugins[i__y]); + } + + return new Promise(function (resolve, reject) { + Promise.all(list.map(loadPlugin)).then(function () { + require(["packageManager"], function (packageManager) { + packageManager.init().then(resolve, reject); + }); + }, reject); + }); } function loadPlugin(url) { - return new Promise(function(resolve, reject) { - require(["pluginManager"], function(pluginManager) { - pluginManager.loadPlugin(url).then(resolve, reject) - }) - }) + return new Promise(function (resolve, reject) { + require(["pluginManager"], function (pluginManager) { + pluginManager.loadPlugin(url).then(resolve, reject); + }); + }); } function enableNativeGamepadKeyMapping() { - return !(!window.navigator || "string" != typeof window.navigator.gamepadInputEmulation) && (window.navigator.gamepadInputEmulation = "keyboard", !0) + if (!(!window.navigator || "string" != typeof window.navigator.gamepadInputEmulation)) { + window.navigator.gamepadInputEmulation = "keyboard"; + return true; + } + + return false; } function isGamepadSupported() { - return "ongamepadconnected" in window || navigator.getGamepads || navigator.webkitGetGamepads + return "ongamepadconnected" in window || navigator.getGamepads || navigator.webkitGetGamepads; } function onAppReady(browser) { console.log("Begin onAppReady"); - var deps = [], - isBackgroundSync = -1 !== self.location.href.toString().toLowerCase().indexOf("start=backgroundsync"), - isInBackground = isBackgroundSync; - deps.push("apphost"), isInBackground || (deps.push("appRouter"), deps.push("scripts/themeloader"), browser.iOS && deps.push("css!devices/ios/ios.css"), deps.push("libraryMenu")), console.log("onAppReady - loading dependencies"), require(deps, function(appHost, pageObjects) { - if (console.log("Loaded dependencies in onAppReady"), window.Emby = {}, isBackgroundSync) return void syncNow(); - window.Emby.Page = pageObjects, defineCoreRoutes(appHost), Emby.Page.start({ - click: !1, - hashbang: !0 + var deps = []; + var isBackgroundSync = -1 !== self.location.href.toString().toLowerCase().indexOf("start=backgroundsync"); + var isInBackground = isBackgroundSync; + deps.push("apphost"); + + if (!isInBackground) { + deps.push("appRouter"); + deps.push("scripts/themeloader"); + + if (browser.iOS) { + deps.push("css!devices/ios/ios.css"); + } + + deps.push("libraryMenu"); + } + + console.log("onAppReady - loading dependencies"); + + require(deps, function (appHost, pageObjects) { + if (console.log("Loaded dependencies in onAppReady"), window.Emby = {}, isBackgroundSync) { + return void syncNow(); + } + + window.Emby.Page = pageObjects; + defineCoreRoutes(appHost); + Emby.Page.start({ + click: false, + hashbang: true }); var postInitDependencies = []; - !enableNativeGamepadKeyMapping() && isGamepadSupported() && postInitDependencies.push("bower_components/emby-webcomponents/input/gamepadtokey"), postInitDependencies.push("bower_components/emby-webcomponents/thememediaplayer"), postInitDependencies.push("scripts/autobackdrops"), "cordova" !== self.appMode && "android" !== self.appMode || (browser.android ? (postInitDependencies.push("cordova/mediasession"), postInitDependencies.push("cordova/chromecast"), postInitDependencies.push("cordova/appshortcuts")) : browser.safari && (postInitDependencies.push("cordova/mediasession"), postInitDependencies.push("cordova/volume"), postInitDependencies.push("cordova/statusbar"), postInitDependencies.push("cordova/backgroundfetch"))), browser.tv || browser.xboxOne || browser.ps4 || postInitDependencies.push("bower_components/emby-webcomponents/nowplayingbar/nowplayingbar"), appHost.supports("remotecontrol") && (postInitDependencies.push("playerSelectionMenu"), postInitDependencies.push("bower_components/emby-webcomponents/playback/remotecontrolautoplay")), appHost.supports("physicalvolumecontrol") && !browser.touch || browser.edge || postInitDependencies.push("bower_components/emby-webcomponents/playback/volumeosd"), navigator.mediaSession && postInitDependencies.push("mediaSession"), postInitDependencies.push("apiInput"), postInitDependencies.push("mouseManager"), browser.tv || browser.xboxOne || (postInitDependencies.push("bower_components/emby-webcomponents/playback/playbackorientation"), registerServiceWorker(), window.Notification && postInitDependencies.push("bower_components/emby-webcomponents/notifications/notifications")), postInitDependencies.push("playerSelectionMenu"), appHost.supports("fullscreenchange") && (browser.edgeUwp || -1 !== navigator.userAgent.toLowerCase().indexOf("electron")) && require(["fullscreen-doubleclick"]), require(postInitDependencies), appHost.supports("sync") && initLocalSyncEvents(), AppInfo.isNativeApp || window.ApiClient && require(["css!" + ApiClient.getUrl("Branding/Css")]) - }) + + if (!enableNativeGamepadKeyMapping() && isGamepadSupported()) { + postInitDependencies.push("bower_components/emby-webcomponents/input/gamepadtokey"); + } + + postInitDependencies.push("bower_components/emby-webcomponents/thememediaplayer"); + postInitDependencies.push("scripts/autobackdrops"); + + if (!("cordova" !== self.appMode && "android" !== self.appMode)) { + if (browser.android) { + postInitDependencies.push("cordova/mediasession"); + postInitDependencies.push("cordova/chromecast"); + postInitDependencies.push("cordova/appshortcuts"); + } else { + if (browser.safari) { + postInitDependencies.push("cordova/mediasession"); + postInitDependencies.push("cordova/volume"); + postInitDependencies.push("cordova/statusbar"); + postInitDependencies.push("cordova/backgroundfetch"); + } + } + } + + if (!(browser.tv || browser.xboxOne || browser.ps4)) { + postInitDependencies.push("bower_components/emby-webcomponents/nowplayingbar/nowplayingbar"); + } + + if (appHost.supports("remotecontrol")) { + postInitDependencies.push("playerSelectionMenu"); + postInitDependencies.push("bower_components/emby-webcomponents/playback/remotecontrolautoplay"); + } + + if (!(appHost.supports("physicalvolumecontrol") && !browser.touch || browser.edge)) { + postInitDependencies.push("bower_components/emby-webcomponents/playback/volumeosd"); + } + + if (navigator.mediaSession) { + postInitDependencies.push("mediaSession"); + } + + postInitDependencies.push("apiInput"); + postInitDependencies.push("mouseManager"); + + if (!(browser.tv || browser.xboxOne)) { + postInitDependencies.push("bower_components/emby-webcomponents/playback/playbackorientation"); + registerServiceWorker(); + + if (window.Notification) { + postInitDependencies.push("bower_components/emby-webcomponents/notifications/notifications"); + } + } + + postInitDependencies.push("playerSelectionMenu"); + + if (appHost.supports("fullscreenchange") && (browser.edgeUwp || -1 !== navigator.userAgent.toLowerCase().indexOf("electron"))) { + require(["fullscreen-doubleclick"]); + } + + require(postInitDependencies); + + if (appHost.supports("sync")) { + initLocalSyncEvents(); + } + + if (!AppInfo.isNativeApp) { + if (window.ApiClient) { + require(["css!" + ApiClient.getUrl("Branding/Css")]); + } + } + }); } function registerServiceWorker() { - if (navigator.serviceWorker && "cordova" !== self.appMode && "android" !== self.appMode) try { - navigator.serviceWorker.register("serviceworker.js").then(function() { - return navigator.serviceWorker.ready - }).then(function(reg) { - if (reg && reg.sync) return reg.sync.register("emby-sync").then(function() { - // TODO cvium: the sync serviceworker is a noop? - //window.SyncRegistered = Dashboard.isConnectMode() - }) - }) - } catch (err) { - console.log("Error registering serviceWorker: " + err) + if (navigator.serviceWorker && "cordova" !== self.appMode && "android" !== self.appMode) { + try { + navigator.serviceWorker.register("serviceworker.js").then(function () { + return navigator.serviceWorker.ready; + }).then(function (reg) { + if (reg && reg.sync) { + return reg.sync.register("emby-sync").then(function () {// TODO cvium: the sync serviceworker is a noop? + //window.SyncRegistered = Dashboard.isConnectMode() + }); + } + }); + } catch (err) { + console.log("Error registering serviceWorker: " + err); + } } } function syncNow() { - require(["localsync"], function(localSync) { - localSync.sync() - }) + require(["localsync"], function (localSync) { + localSync.sync(); + }); } function initLocalSyncEvents() { - require(["serverNotifications", "events"], function(serverNotifications, events) { - events.on(serverNotifications, "SyncJobItemReady", syncNow), events.on(serverNotifications, "SyncJobCancelled", syncNow), events.on(serverNotifications, "SyncJobItemCancelled", syncNow) - }) + require(["serverNotifications", "events"], function (serverNotifications, events) { + events.on(serverNotifications, "SyncJobItemReady", syncNow); + events.on(serverNotifications, "SyncJobCancelled", syncNow); + events.on(serverNotifications, "SyncJobItemCancelled", syncNow); + }); } function onWebComponentsReady(browser) { var initialDependencies = []; + if (!window.Promise || browser.web0s) { initialDependencies.push("bower_components/emby-webcomponents/native-promise-only/lib/npo.src"); } + initRequireWithBrowser(browser); + if (self.appMode === 'cordova' || self.appMode === 'android' || self.appMode === 'standalone') { AppInfo.isNativeApp = true; } + require(initialDependencies, init); } var localApiClient; - return function() { - var urlArgs = "v=" + (window.dashboardVersion || (new Date).getDate()); + + (function () { + var urlArgs = "v=" + (window.dashboardVersion || new Date().getDate()); var bowerPath = getBowerPath(); var apiClientBowerPath = bowerPath + "/emby-apiclient"; var embyWebComponentsBowerPath = bowerPath + "/emby-webcomponents"; var paths = { - velocity: bowerPath + "/velocity/velocity.min", - vibrant: bowerPath + "/vibrant/dist/vibrant", - staticBackdrops: embyWebComponentsBowerPath + "/staticbackdrops", - ironCardList: "components/ironcardlist/ironcardlist", - scrollThreshold: "components/scrollthreshold", - playlisteditor: "components/playlisteditor/playlisteditor", - medialibrarycreator: "components/medialibrarycreator/medialibrarycreator", - medialibraryeditor: "components/medialibraryeditor/medialibraryeditor", - imageoptionseditor: "components/imageoptionseditor/imageoptionseditor", - howler: bowerPath + "/howlerjs/dist/howler.min", - sortable: bowerPath + "/Sortable/Sortable.min", - isMobile: bowerPath + "/isMobile/isMobile.min", - masonry: bowerPath + "/masonry/dist/masonry.pkgd.min", - humanedate: "components/humanedate", - libraryBrowser: "scripts/librarybrowser", - events: apiClientBowerPath + "/events", - credentialprovider: apiClientBowerPath + "/credentials", - connectionManagerFactory: bowerPath + "/emby-apiclient/connectionmanager", - visibleinviewport: embyWebComponentsBowerPath + "/visibleinviewport", - browserdeviceprofile: embyWebComponentsBowerPath + "/browserdeviceprofile", - browser: embyWebComponentsBowerPath + "/browser", - inputManager: embyWebComponentsBowerPath + "/inputmanager", - qualityoptions: embyWebComponentsBowerPath + "/qualityoptions", - hammer: bowerPath + "/hammerjs/hammer.min", - pageJs: embyWebComponentsBowerPath + "/pagejs/page", - focusManager: embyWebComponentsBowerPath + "/focusmanager", - datetime: embyWebComponentsBowerPath + "/datetime", - globalize: embyWebComponentsBowerPath + "/globalize", - itemHelper: embyWebComponentsBowerPath + "/itemhelper", - itemShortcuts: embyWebComponentsBowerPath + "/shortcuts", - playQueueManager: embyWebComponentsBowerPath + "/playback/playqueuemanager", - autoPlayDetect: embyWebComponentsBowerPath + "/playback/autoplaydetect", - nowPlayingHelper: embyWebComponentsBowerPath + "/playback/nowplayinghelper", - pluginManager: embyWebComponentsBowerPath + "/pluginmanager", - packageManager: embyWebComponentsBowerPath + "/packagemanager" + velocity: bowerPath + "/velocity/velocity.min", + vibrant: bowerPath + "/vibrant/dist/vibrant", + staticBackdrops: embyWebComponentsBowerPath + "/staticbackdrops", + ironCardList: "components/ironcardlist/ironcardlist", + scrollThreshold: "components/scrollthreshold", + playlisteditor: "components/playlisteditor/playlisteditor", + medialibrarycreator: "components/medialibrarycreator/medialibrarycreator", + medialibraryeditor: "components/medialibraryeditor/medialibraryeditor", + imageoptionseditor: "components/imageoptionseditor/imageoptionseditor", + howler: bowerPath + "/howlerjs/dist/howler.min", + sortable: bowerPath + "/Sortable/Sortable.min", + isMobile: bowerPath + "/isMobile/isMobile.min", + masonry: bowerPath + "/masonry/dist/masonry.pkgd.min", + humanedate: "components/humanedate", + libraryBrowser: "scripts/librarybrowser", + events: apiClientBowerPath + "/events", + credentialprovider: apiClientBowerPath + "/credentials", + connectionManagerFactory: bowerPath + "/emby-apiclient/connectionmanager", + visibleinviewport: embyWebComponentsBowerPath + "/visibleinviewport", + browserdeviceprofile: embyWebComponentsBowerPath + "/browserdeviceprofile", + browser: embyWebComponentsBowerPath + "/browser", + inputManager: embyWebComponentsBowerPath + "/inputmanager", + qualityoptions: embyWebComponentsBowerPath + "/qualityoptions", + hammer: bowerPath + "/hammerjs/hammer.min", + pageJs: embyWebComponentsBowerPath + "/pagejs/page", + focusManager: embyWebComponentsBowerPath + "/focusmanager", + datetime: embyWebComponentsBowerPath + "/datetime", + globalize: embyWebComponentsBowerPath + "/globalize", + itemHelper: embyWebComponentsBowerPath + "/itemhelper", + itemShortcuts: embyWebComponentsBowerPath + "/shortcuts", + playQueueManager: embyWebComponentsBowerPath + "/playback/playqueuemanager", + autoPlayDetect: embyWebComponentsBowerPath + "/playback/autoplaydetect", + nowPlayingHelper: embyWebComponentsBowerPath + "/playback/nowplayinghelper", + pluginManager: embyWebComponentsBowerPath + "/pluginmanager", + packageManager: embyWebComponentsBowerPath + "/packagemanager" }; - paths.hlsjs = bowerPath + "/hlsjs/dist/hls.min"; paths.flvjs = embyWebComponentsBowerPath + "/flvjs/flv.min"; paths.shaka = embyWebComponentsBowerPath + "/shaka/shaka-player.compiled"; - define("chromecastHelper", [embyWebComponentsBowerPath + "/chromecast/chromecasthelpers"], returnFirstDependency); define("mediaSession", [embyWebComponentsBowerPath + "/playback/mediasession"], returnFirstDependency); define("webActionSheet", [embyWebComponentsBowerPath + "/actionsheet/actionsheet"], returnFirstDependency); @@ -1096,14 +1503,20 @@ var Dashboard = { define("guide-settings-dialog", [embyWebComponentsBowerPath + "/guide/guide-settings"], returnFirstDependency); define("loadingDialog", [embyWebComponentsBowerPath + "/loadingdialog/loadingdialog"], returnFirstDependency); define("syncDialog", [embyWebComponentsBowerPath + "/sync/sync"], returnFirstDependency); - define("viewManager", [embyWebComponentsBowerPath + "/viewmanager/viewmanager"], function(viewManager) { - return window.ViewManager = viewManager, viewManager.dispatchPageEvents(!0), viewManager + define("viewManager", [embyWebComponentsBowerPath + "/viewmanager/viewmanager"], function (viewManager) { + window.ViewManager = viewManager; + viewManager.dispatchPageEvents(true); + return viewManager; }); - "cordova" === self.appMode || "android" === self.appMode - ? paths.apphost = "cordova/apphost" - : paths.apphost = "components/apphost"; - paths.appStorage = getAppStorage(apiClientBowerPath), requirejs.config({ + if ("cordova" === self.appMode || "android" === self.appMode) { + paths.apphost = "cordova/apphost"; + } else { + paths.apphost = "components/apphost"; + } + + paths.appStorage = getAppStorage(apiClientBowerPath); + requirejs.config({ waitSeconds: 0, map: { "*": { @@ -1138,9 +1551,12 @@ var Dashboard = { define("sortMenu", [embyWebComponentsBowerPath + "/sortmenu/sortmenu"], returnFirstDependency); define("registrationServices", [embyWebComponentsBowerPath + "/registrationservices/registrationservices"], returnFirstDependency); - "cordova" === self.appMode || "android" === self.appMode - ? define("fileupload", ["cordova/fileupload"], returnFirstDependency) - : define("fileupload", [apiClientBowerPath + "/fileupload"], returnFirstDependency); + if ("cordova" === self.appMode || "android" === self.appMode) { + define("fileupload", ["cordova/fileupload"], returnFirstDependency); + } else { + define("fileupload", [apiClientBowerPath + "/fileupload"], returnFirstDependency); + } + define("connectionmanager", [apiClientBowerPath + "/connectionmanager"]); define("serversync", [apiClientBowerPath + "/sync/serversync"], returnFirstDependency); define("multiserversync", [apiClientBowerPath + "/sync/multiserversync"], returnFirstDependency); @@ -1165,11 +1581,15 @@ var Dashboard = { define("navdrawer", ["components/navdrawer/navdrawer"], returnFirstDependency); define("htmlMediaHelper", [embyWebComponentsBowerPath + "/htmlvideoplayer/htmlmediahelper"], returnFirstDependency); define("viewcontainer", ["components/viewcontainer-lite", "css!" + embyWebComponentsBowerPath + "/viewmanager/viewcontainer-lite"], returnFirstDependency); - define("queryString", [bowerPath + "/query-string/index"], function() { - return queryString + define("queryString", [bowerPath + "/query-string/index"], function () { + return queryString; }); - define("jQuery", [bowerPath + "/jquery/dist/jquery.slim.min"], function() { - return window.ApiClient && (jQuery.ajax = ApiClient.ajax), jQuery + define("jQuery", [bowerPath + "/jquery/dist/jquery.slim.min"], function () { + if (window.ApiClient) { + jQuery.ajax = ApiClient.ajax; + } + + return jQuery; }); define("fnchecked", ["legacy/fnchecked"], returnFirstDependency); define("dialogHelper", [embyWebComponentsBowerPath + "/dialoghelper/dialoghelper"], returnFirstDependency); @@ -1178,12 +1598,20 @@ var Dashboard = { define("serverNotifications", ["apiInput"], returnFirstDependency); define("headroom-window", ["headroom"], createWindowHeadroom); define("appFooter-shared", ["appFooter"], createSharedAppFooter); - define("skinManager", [embyWebComponentsBowerPath + "/skinmanager"], function(skinManager) { - return skinManager.loadUserSkin = function(options) { - require(["appRouter"], function(appRouter) { - options = options || {}, options.start ? appRouter.invokeShortcut(options.start) : appRouter.goHome() - }) - }, skinManager.getThemes = function() { + define("skinManager", [embyWebComponentsBowerPath + "/skinmanager"], function (skinManager) { + skinManager.loadUserSkin = function (options) { + require(["appRouter"], function (appRouter) { + options = options || {}; + + if (options.start) { + appRouter.invokeShortcut(options.start); + } else { + appRouter.goHome(); + } + }); + }; + + skinManager.getThemes = function () { return [{ name: "Apple TV", id: "appletv" @@ -1193,8 +1621,8 @@ var Dashboard = { }, { name: "Dark", id: "dark", - isDefault: !0, - isDefaultServerDashboard: !0 + isDefault: true, + isDefaultServerDashboard: true }, { name: "Dark (green accent)", id: "dark-green" @@ -1203,7 +1631,7 @@ var Dashboard = { id: "dark-red" }, { name: "Light", - id: "light", + id: "light" }, { name: "Light (blue accent)", id: "light-blue" @@ -1222,103 +1650,314 @@ var Dashboard = { }, { name: "Windows Media Center", id: "wmc" - }] - }, skinManager + }]; + }; + + return skinManager; }); - define("connectionManager", [], function() { - return ConnectionManager + define("connectionManager", [], function () { + return ConnectionManager; }); - define("apiClientResolver", [], function() { - return function() { - return window.ApiClient - } + define("apiClientResolver", [], function () { + return function () { + return window.ApiClient; + }; }); - define("appRouter", [embyWebComponentsBowerPath + "/router", "itemHelper"], function(appRouter, itemHelper) { + define("appRouter", [embyWebComponentsBowerPath + "/router", "itemHelper"], function (appRouter, itemHelper) { function showItem(item, serverId, options) { - "string" == typeof item ? require(["connectionManager"], function(connectionManager) { - var apiClient = connectionManager.currentApiClient(); - apiClient.getItem(apiClient.getCurrentUserId(), item).then(function(item) { - appRouter.showItem(item, options) - }) - }) : (2 == arguments.length && (options = arguments[1]), appRouter.show("/" + appRouter.getRouteUrl(item, options), { - item: item - })) + if ("string" == typeof item) { + require(["connectionManager"], function (connectionManager) { + var apiClient = connectionManager.currentApiClient(); + apiClient.getItem(apiClient.getCurrentUserId(), item).then(function (item) { + appRouter.showItem(item, options); + }); + }); + } else { + if (2 == arguments.length) { + options = arguments[1]; + } + + appRouter.show("/" + appRouter.getRouteUrl(item, options), { + item: item + }); + } } - return appRouter.showLocalLogin = function(serverId, manualLogin) { - Dashboard.navigate("login.html?serverid=" + serverId) - }, appRouter.showVideoOsd = function() { - return Dashboard.navigate("videoosd.html") - }, appRouter.showSelectServer = function() { - Dashboard.navigate(AppInfo.isNativeApp ? "selectserver.html" : "login.html") - }, appRouter.showWelcome = function() { - Dashboard.navigate(AppInfo.isNativeApp ? "selectserver.html" : "login.html") - }, appRouter.showSettings = function() { - Dashboard.navigate("mypreferencesmenu.html") - }, appRouter.showGuide = function() { - Dashboard.navigate("livetv.html?tab=1") - }, appRouter.goHome = function() { - Dashboard.navigate("home.html") - }, appRouter.showSearch = function() { - Dashboard.navigate("search.html") - }, appRouter.showLiveTV = function() { - Dashboard.navigate("livetv.html") - }, appRouter.showRecordedTV = function() { - Dashboard.navigate("livetv.html?tab=3") - }, appRouter.showFavorites = function() { - Dashboard.navigate("home.html?tab=1") - }, appRouter.showSettings = function() { - Dashboard.navigate("mypreferencesmenu.html") - }, appRouter.showNowPlaying = function() { - Dashboard.navigate("nowplaying.html") - }, appRouter.setTitle = function(title) { - LibraryMenu.setTitle(title) - }, appRouter.getRouteUrl = function(item, options) { - if (!item) throw new Error("item cannot be null"); - if (item.url) return item.url; - var context = options ? options.context : null, - id = item.Id || item.ItemId; - options || (options = {}); - var url, itemType = item.Type || (options ? options.itemType : null), - serverId = item.ServerId || options.serverId; - if ("settings" === item) return "mypreferencesmenu.html"; - if ("wizard" === item) return "wizardstart.html"; - if ("manageserver" === item) return "dashboard.html"; - if ("recordedtv" === item) return "livetv.html?tab=3&serverId=" + options.serverId; - if ("nextup" === item) return "list/list.html?type=nextup&serverId=" + options.serverId; + + appRouter.showLocalLogin = function (serverId, manualLogin) { + Dashboard.navigate("login.html?serverid=" + serverId); + }; + + appRouter.showVideoOsd = function () { + return Dashboard.navigate("videoosd.html"); + }; + + appRouter.showSelectServer = function () { + Dashboard.navigate(AppInfo.isNativeApp ? "selectserver.html" : "login.html"); + }; + + appRouter.showWelcome = function () { + Dashboard.navigate(AppInfo.isNativeApp ? "selectserver.html" : "login.html"); + }; + + appRouter.showSettings = function () { + Dashboard.navigate("mypreferencesmenu.html"); + }; + + appRouter.showGuide = function () { + Dashboard.navigate("livetv.html?tab=1"); + }; + + appRouter.goHome = function () { + Dashboard.navigate("home.html"); + }; + + appRouter.showSearch = function () { + Dashboard.navigate("search.html"); + }; + + appRouter.showLiveTV = function () { + Dashboard.navigate("livetv.html"); + }; + + appRouter.showRecordedTV = function () { + Dashboard.navigate("livetv.html?tab=3"); + }; + + appRouter.showFavorites = function () { + Dashboard.navigate("home.html?tab=1"); + }; + + appRouter.showSettings = function () { + Dashboard.navigate("mypreferencesmenu.html"); + }; + + appRouter.showNowPlaying = function () { + Dashboard.navigate("nowplaying.html"); + }; + + appRouter.setTitle = function (title) { + LibraryMenu.setTitle(title); + }; + + appRouter.getRouteUrl = function (item, options) { + if (!item) { + throw new Error("item cannot be null"); + } + + if (item.url) { + return item.url; + } + + var context = options ? options.context : null; + var id = item.Id || item.ItemId; + + if (!options) { + options = {}; + } + + var url; + var itemType = item.Type || (options ? options.itemType : null); + var serverId = item.ServerId || options.serverId; + + if ("settings" === item) { + return "mypreferencesmenu.html"; + } + + if ("wizard" === item) { + return "wizardstart.html"; + } + + if ("manageserver" === item) { + return "dashboard.html"; + } + + if ("recordedtv" === item) { + return "livetv.html?tab=3&serverId=" + options.serverId; + } + + if ("nextup" === item) { + return "list/list.html?type=nextup&serverId=" + options.serverId; + } + if ("list" === item) { var url = "list/list.html?serverId=" + options.serverId + "&type=" + options.itemTypes; - return options.isFavorite && (url += "&IsFavorite=true"), url - } - if ("livetv" === item) return "guide" === options.section ? "livetv.html?tab=1&serverId=" + options.serverId : "movies" === options.section ? "list/list.html?type=Programs&IsMovie=true&serverId=" + options.serverId : "shows" === options.section ? "list/list.html?type=Programs&IsSeries=true&IsMovie=false&IsNews=false&serverId=" + options.serverId : "sports" === options.section ? "list/list.html?type=Programs&IsSports=true&serverId=" + options.serverId : "kids" === options.section ? "list/list.html?type=Programs&IsKids=true&serverId=" + options.serverId : "news" === options.section ? "list/list.html?type=Programs&IsNews=true&serverId=" + options.serverId : "onnow" === options.section ? "list/list.html?type=Programs&IsAiring=true&serverId=" + options.serverId : "dvrschedule" === options.section ? "livetv.html?tab=4&serverId=" + options.serverId : "livetv.html?serverId=" + options.serverId; - if ("SeriesTimer" == itemType) return "itemdetails.html?seriesTimerId=" + id + "&serverId=" + serverId; - if ("livetv" == item.CollectionType) return "livetv.html"; - if ("Genre" === item.Type) return url = "list/list.html?genreId=" + item.Id + "&serverId=" + serverId, "livetv" === context && (url += "&type=Programs"), options.parentId && (url += "&parentId=" + options.parentId), url; - if ("MusicGenre" === item.Type) return url = "list/list.html?musicGenreId=" + item.Id + "&serverId=" + serverId, options.parentId && (url += "&parentId=" + options.parentId), url; - if ("Studio" === item.Type) return url = "list/list.html?studioId=" + item.Id + "&serverId=" + serverId, options.parentId && (url += "&parentId=" + options.parentId), url; - if ("folders" !== context && !itemHelper.isLocalItem(item)) { - if ("movies" == item.CollectionType) return url = "movies.html?topParentId=" + item.Id, options && "latest" === options.section && (url += "&tab=1"), url; - if ("tvshows" == item.CollectionType) return url = "tv.html?topParentId=" + item.Id, options && "latest" === options.section && (url += "&tab=2"), url; - if ("music" == item.CollectionType) return "music.html?topParentId=" + item.Id - } - if ("Playlist" == itemType) return "itemdetails.html?id=" + id + "&serverId=" + serverId; - if ("TvChannel" == itemType) return "itemdetails.html?id=" + id + "&serverId=" + serverId; - if ("Program" == itemType) return "itemdetails.html?id=" + id + "&serverId=" + serverId; - if ("BoxSet" == itemType) return "itemdetails.html?id=" + id + "&serverId=" + serverId; - if ("MusicAlbum" == itemType) return "itemdetails.html?id=" + id + "&serverId=" + serverId; - if ("MusicGenre" == itemType) return "itemdetails.html?id=" + id + "&serverId=" + serverId; - if ("Person" == itemType) return "itemdetails.html?id=" + id + "&serverId=" + serverId; - if ("Recording" == itemType) return "itemdetails.html?id=" + id + "&serverId=" + serverId; - if ("MusicArtist" == itemType) return "itemdetails.html?id=" + id + "&serverId=" + serverId; - var contextSuffix = context ? "&context=" + context : ""; - return "Series" == itemType || "Season" == itemType || "Episode" == itemType ? "itemdetails.html?id=" + id + contextSuffix + "&serverId=" + serverId : item.IsFolder ? id ? "list/list.html?parentId=" + id + "&serverId=" + serverId : "#" : "itemdetails.html?id=" + id + "&serverId=" + serverId - }, appRouter.showItem = showItem, appRouter - }) - }(), require(["css!css/site"]), require(["browser"], onWebComponentsReady) -}(); -pageClassOn("viewshow", "standalonePage", function() { + if (options.isFavorite) { + url += "&IsFavorite=true"; + } + + return url; + } + + if ("livetv" === item) { + if ("guide" === options.section) { + return "livetv.html?tab=1&serverId=" + options.serverId; + } + + if ("movies" === options.section) { + return "list/list.html?type=Programs&IsMovie=true&serverId=" + options.serverId; + } + + if ("shows" === options.section) { + return "list/list.html?type=Programs&IsSeries=true&IsMovie=false&IsNews=false&serverId=" + options.serverId; + } + + if ("sports" === options.section) { + return "list/list.html?type=Programs&IsSports=true&serverId=" + options.serverId; + } + + if ("kids" === options.section) { + return "list/list.html?type=Programs&IsKids=true&serverId=" + options.serverId; + } + + if ("news" === options.section) { + return "list/list.html?type=Programs&IsNews=true&serverId=" + options.serverId; + } + + if ("onnow" === options.section) { + return "list/list.html?type=Programs&IsAiring=true&serverId=" + options.serverId; + } + + if ("dvrschedule" === options.section) { + return "livetv.html?tab=4&serverId=" + options.serverId; + } + + return "livetv.html?serverId=" + options.serverId; + } + + if ("SeriesTimer" == itemType) { + return "itemdetails.html?seriesTimerId=" + id + "&serverId=" + serverId; + } + + if ("livetv" == item.CollectionType) { + return "livetv.html"; + } + + if ("Genre" === item.Type) { + url = "list/list.html?genreId=" + item.Id + "&serverId=" + serverId; + + if ("livetv" === context) { + url += "&type=Programs"; + } + + if (options.parentId) { + url += "&parentId=" + options.parentId; + } + + return url; + } + + if ("MusicGenre" === item.Type) { + url = "list/list.html?musicGenreId=" + item.Id + "&serverId=" + serverId; + + if (options.parentId) { + url += "&parentId=" + options.parentId; + } + + return url; + } + + if ("Studio" === item.Type) { + url = "list/list.html?studioId=" + item.Id + "&serverId=" + serverId; + + if (options.parentId) { + url += "&parentId=" + options.parentId; + } + + return url; + } + + if ("folders" !== context && !itemHelper.isLocalItem(item)) { + if ("movies" == item.CollectionType) { + url = "movies.html?topParentId=" + item.Id; + + if (options && "latest" === options.section) { + url += "&tab=1"; + } + + return url; + } + + if ("tvshows" == item.CollectionType) { + url = "tv.html?topParentId=" + item.Id; + + if (options && "latest" === options.section) { + url += "&tab=2"; + } + + return url; + } + + if ("music" == item.CollectionType) { + return "music.html?topParentId=" + item.Id; + } + } + + if ("Playlist" == itemType) { + return "itemdetails.html?id=" + id + "&serverId=" + serverId; + } + + if ("TvChannel" == itemType) { + return "itemdetails.html?id=" + id + "&serverId=" + serverId; + } + + if ("Program" == itemType) { + return "itemdetails.html?id=" + id + "&serverId=" + serverId; + } + + if ("BoxSet" == itemType) { + return "itemdetails.html?id=" + id + "&serverId=" + serverId; + } + + if ("MusicAlbum" == itemType) { + return "itemdetails.html?id=" + id + "&serverId=" + serverId; + } + + if ("MusicGenre" == itemType) { + return "itemdetails.html?id=" + id + "&serverId=" + serverId; + } + + if ("Person" == itemType) { + return "itemdetails.html?id=" + id + "&serverId=" + serverId; + } + + if ("Recording" == itemType) { + return "itemdetails.html?id=" + id + "&serverId=" + serverId; + } + + if ("MusicArtist" == itemType) { + return "itemdetails.html?id=" + id + "&serverId=" + serverId; + } + + var contextSuffix = context ? "&context=" + context : ""; + + if ("Series" == itemType || "Season" == itemType || "Episode" == itemType) { + return "itemdetails.html?id=" + id + contextSuffix + "&serverId=" + serverId; + } + + if (item.IsFolder) { + if (id) { + return "list/list.html?parentId=" + id + "&serverId=" + serverId; + } + + return "#"; + } + + return "itemdetails.html?id=" + id + "&serverId=" + serverId; + }; + + appRouter.showItem = showItem; + return appRouter; + }); + })(); + + require(["css!css/site"]); + + return require(["browser"], onWebComponentsReady); +}(); +pageClassOn("viewshow", "standalonePage", function () { document.querySelector(".skinHeader").classList.add("noHeaderRight"); }); -pageClassOn("viewhide", "standalonePage", function() { +pageClassOn("viewhide", "standalonePage", function () { document.querySelector(".skinHeader").classList.remove("noHeaderRight"); }); From e272b12755e300d28ce5d7788cf86843e36429f3 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 23 Feb 2019 17:12:14 +0000 Subject: [PATCH 015/220] refactor dynamic require dependencies for webpack --- src/scripts/site.js | 252 ++++++++++++++++++++------------------------ 1 file changed, 117 insertions(+), 135 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 64b254ba13..d30d27f9ea 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -282,33 +282,42 @@ var AppInfo = {}; } function createConnectionManager() { - return new Promise(function (resolve, reject) { - require(["connectionManagerFactory", "apphost", "credentialprovider", "events", "userSettings"], function (ConnectionManager, apphost, credentialProvider, events, userSettings) { - var credentialProviderInstance = new credentialProvider(); - var promises = [apphost.getSyncProfile(), apphost.init()]; - Promise.all(promises).then(function (responses) { - var deviceProfile = responses[0]; - var capabilities = Dashboard.capabilities(apphost); - capabilities.DeviceProfile = deviceProfile; - var connectionManager = new ConnectionManager(credentialProviderInstance, apphost.appName(), apphost.appVersion(), apphost.deviceName(), apphost.deviceId(), capabilities, window.devicePixelRatio); + return require(["connectionManagerFactory", "apphost", "credentialprovider", "events", "userSettings"], function (ConnectionManager, apphost, credentialProvider, events, userSettings) { + var credentialProviderInstance = new credentialProvider(), + promises = [apphost.getSyncProfile(), apphost.init()]; - if (defineConnectionManager(connectionManager), bindConnectionManagerEvents(connectionManager, events, userSettings), !AppInfo.isNativeApp) { - console.log("loading ApiClient singleton"); - return getRequirePromise(["apiclient"]).then(function (apiClientFactory) { - console.log("creating ApiClient singleton"); - var apiClient = new apiClientFactory(Dashboard.serverAddress(), apphost.appName(), apphost.appVersion(), apphost.deviceName(), apphost.deviceId(), window.devicePixelRatio); - apiClient.enableAutomaticNetworking = false; - apiClient.manualAddressOnly = true; - connectionManager.addApiClient(apiClient); - window.ApiClient = apiClient; - localApiClient = apiClient; - console.log("loaded ApiClient singleton"); - resolve(); - }); - } + Promise.all(promises).then(function (responses) { + var deviceProfile = responses[0], + capabilities = Dashboard.capabilities(apphost); - resolve(); - }); + capabilities.DeviceProfile = deviceProfile; + + var connectionManager = new ConnectionManager(credentialProviderInstance, apphost.appName(), apphost.appVersion(), apphost.deviceName(), apphost.deviceId(), capabilities, window.devicePixelRatio); + + defineConnectionManager(connectionManager); + bindConnectionManagerEvents(connectionManager, events, userSettings); + + if (!AppInfo.isNativeApp) { + console.log("loading ApiClient singleton"); + + return require(["apiclient"], function (apiClientFactory) { + console.log("creating ApiClient singleton"); + + var apiClient = new apiClientFactory(Dashboard.serverAddress(), apphost.appName(), apphost.appVersion(), apphost.deviceName(), apphost.deviceId(), window.devicePixelRatio); + + apiClient.enableAutomaticNetworking = false; + apiClient.manualAddressOnly = true; + + connectionManager.addApiClient(apiClient); + + window.ApiClient = apiClient; + localApiClient = apiClient; + + console.log("loaded ApiClient singleton"); + }); + } + + return Promise.resolve(); }); }); } @@ -551,12 +560,6 @@ var AppInfo = {}; } } - function getRequirePromise(deps) { - return new Promise(function (resolve, reject) { - require(deps, resolve); - }); - } - function init() { if ("android" === self.appMode) { define("nativedirectorychooser", ["cordova/nativedirectorychooser"], returnFirstDependency); @@ -565,29 +568,29 @@ var AppInfo = {}; define("livetvcss", ["css!css/livetv.css"], returnFirstDependency); define("detailtablecss", ["css!css/detailtable.css"], returnFirstDependency); define("buttonenabled", ["legacy/buttonenabled"], returnFirstDependency); - var list = []; + var promises = []; if (!window.fetch) { - list.push("fetch"); + promises.push(require(["fetch"])); } if ("function" != typeof Object.assign) { - list.push("objectassign"); + promises.push(require(["objectassign"])); } if (!Array.prototype.filter) { - list.push("arraypolyfills"); + promises.push(require(["arraypolyfills"])); } if (!Function.prototype.bind) { - list.push("functionbind"); + promises.push(require(["functionbind"])); } if (!window.requestAnimationFrame) { - list.push("raf"); + promises.push(require(["raf"])); } - require(list, function () { + Promise.all(promises).then(function () { createConnectionManager().then(function () { console.log("initAfterDependencies promises resolved"); @@ -624,19 +627,16 @@ var AppInfo = {}; } document.title = Globalize.translateDocument(document.title, "core"); - var deps = ["apphost"]; if (browser.tv && !browser.android) { console.log("Using system fonts with explicit sizes"); - deps.push("systemFontsSizedCss"); + require(["systemFontsSizedCss"]); } else { console.log("Using default fonts"); - deps.push("systemFontsCss"); + require(["systemFontsCss"]); } - deps.push("css!css/librarybrowser"); - - require(deps, function (appHost) { + require(["apphost", "css!css/librarybrowser"], function (appHost) { loadPlugins([], appHost, browser).then(function () { onAppReady(browser); }); @@ -1219,106 +1219,89 @@ var AppInfo = {}; function onAppReady(browser) { console.log("Begin onAppReady"); - var deps = []; - var isBackgroundSync = -1 !== self.location.href.toString().toLowerCase().indexOf("start=backgroundsync"); - var isInBackground = isBackgroundSync; - deps.push("apphost"); - if (!isInBackground) { - deps.push("appRouter"); - deps.push("scripts/themeloader"); + var isInBackground = -1 !== self.location.href.toString().toLowerCase().indexOf("start=backgroundsync"); - if (browser.iOS) { - deps.push("css!devices/ios/ios.css"); - } - - deps.push("libraryMenu"); - } + window.Emby = {}; console.log("onAppReady - loading dependencies"); - require(deps, function (appHost, pageObjects) { - if (console.log("Loaded dependencies in onAppReady"), window.Emby = {}, isBackgroundSync) { - return void syncNow(); + if (isInBackground) { + syncNow(); + } else { + + if (browser.iOS) { + require(['css!devices/ios/ios.css']); } - window.Emby.Page = pageObjects; - defineCoreRoutes(appHost); - Emby.Page.start({ - click: false, - hashbang: true - }); - var postInitDependencies = []; + require(['apphost', 'appRouter', 'scripts/themeloader', 'libraryMenu'], function (appHost, pageObjects) { + window.Emby.Page = pageObjects; - if (!enableNativeGamepadKeyMapping() && isGamepadSupported()) { - postInitDependencies.push("bower_components/emby-webcomponents/input/gamepadtokey"); - } + defineCoreRoutes(appHost); - postInitDependencies.push("bower_components/emby-webcomponents/thememediaplayer"); - postInitDependencies.push("scripts/autobackdrops"); + Emby.Page.start({ + click: false, + hashbang: true + }); - if (!("cordova" !== self.appMode && "android" !== self.appMode)) { - if (browser.android) { - postInitDependencies.push("cordova/mediasession"); - postInitDependencies.push("cordova/chromecast"); - postInitDependencies.push("cordova/appshortcuts"); - } else { - if (browser.safari) { - postInitDependencies.push("cordova/mediasession"); - postInitDependencies.push("cordova/volume"); - postInitDependencies.push("cordova/statusbar"); - postInitDependencies.push("cordova/backgroundfetch"); + if (!enableNativeGamepadKeyMapping() && isGamepadSupported()) { + require(["bower_components/emby-webcomponents/input/gamepadtokey"]); + } + + require(["bower_components/emby-webcomponents/thememediaplayer", "scripts/autobackdrops"]); + + if (!("cordova" !== self.appMode && "android" !== self.appMode)) { + if (browser.android) { + require(["cordova/mediasession", "cordova/chromecast", "cordova/appshortcuts"]); + } else if (browser.safari) { + require(["cordova/mediasession", "cordova/volume", "cordova/statusbar", "cordova/backgroundfetch"]); } } - } - if (!(browser.tv || browser.xboxOne || browser.ps4)) { - postInitDependencies.push("bower_components/emby-webcomponents/nowplayingbar/nowplayingbar"); - } - - if (appHost.supports("remotecontrol")) { - postInitDependencies.push("playerSelectionMenu"); - postInitDependencies.push("bower_components/emby-webcomponents/playback/remotecontrolautoplay"); - } - - if (!(appHost.supports("physicalvolumecontrol") && !browser.touch || browser.edge)) { - postInitDependencies.push("bower_components/emby-webcomponents/playback/volumeosd"); - } - - if (navigator.mediaSession) { - postInitDependencies.push("mediaSession"); - } - - postInitDependencies.push("apiInput"); - postInitDependencies.push("mouseManager"); - - if (!(browser.tv || browser.xboxOne)) { - postInitDependencies.push("bower_components/emby-webcomponents/playback/playbackorientation"); - registerServiceWorker(); - - if (window.Notification) { - postInitDependencies.push("bower_components/emby-webcomponents/notifications/notifications"); + if (!(browser.tv || browser.xboxOne || browser.ps4)) { + require(["bower_components/emby-webcomponents/nowplayingbar/nowplayingbar"]); } - } - postInitDependencies.push("playerSelectionMenu"); - - if (appHost.supports("fullscreenchange") && (browser.edgeUwp || -1 !== navigator.userAgent.toLowerCase().indexOf("electron"))) { - require(["fullscreen-doubleclick"]); - } - - require(postInitDependencies); - - if (appHost.supports("sync")) { - initLocalSyncEvents(); - } - - if (!AppInfo.isNativeApp) { - if (window.ApiClient) { - require(["css!" + ApiClient.getUrl("Branding/Css")]); + if (appHost.supports("remotecontrol")) { + require(["playerSelectionMenu", "bower_components/emby-webcomponents/playback/remotecontrolautoplay"]); } - } - }); + + if (!(appHost.supports("physicalvolumecontrol") && !browser.touch || browser.edge)) { + require(["bower_components/emby-webcomponents/playback/volumeosd"]); + } + + if (navigator.mediaSession) { + require(["mediaSession"]); + } + + require(["apiInput", "mouseManager"]); + + if (!(browser.tv || browser.xboxOne)) { + require(["bower_components/emby-webcomponents/playback/playbackorientation"]); + registerServiceWorker(); + + if (window.Notification) { + require(["bower_components/emby-webcomponents/notifications/notifications"]); + } + } + + require(["playerSelectionMenu"]); + + if (appHost.supports("fullscreenchange") && (browser.edgeUwp || -1 !== navigator.userAgent.toLowerCase().indexOf("electron"))) { + require(["fullscreen-doubleclick"]); + } + + if (appHost.supports("sync")) { + initLocalSyncEvents(); + } + + if (!AppInfo.isNativeApp) { + if (window.ApiClient) { + require(["css!" + ApiClient.getUrl("Branding/Css")]); + } + } + }); + } } function registerServiceWorker() { @@ -1354,19 +1337,18 @@ var AppInfo = {}; } function onWebComponentsReady(browser) { - var initialDependencies = []; - - if (!window.Promise || browser.web0s) { - initialDependencies.push("bower_components/emby-webcomponents/native-promise-only/lib/npo.src"); - } - initRequireWithBrowser(browser); if (self.appMode === 'cordova' || self.appMode === 'android' || self.appMode === 'standalone') { AppInfo.isNativeApp = true; } - require(initialDependencies, init); + if (!window.Promise || browser.web0s) { + initialDependencies.push(); + require(["bower_components/emby-webcomponents/native-promise-only/lib/npo.src"], init); + } else { + init(); + } } var localApiClient; From e91cbf843869905a08cd48a4627d113051ab8e24 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 23 Feb 2019 17:12:41 +0000 Subject: [PATCH 016/220] add directory dist to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index ac62bd07a1..cb9b773756 100644 --- a/.gitignore +++ b/.gitignore @@ -573,3 +573,6 @@ ASALocalRun/ healthchecksdb # End of https://www.gitignore.io/api/node,rider,macos,linux,windows,visualstudio,visualstudiocode + +# dist for webpack output +dist \ No newline at end of file From 6ddc62857d2dd07793c4d0a716dad28d5d35fc27 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 23 Feb 2019 18:05:42 +0000 Subject: [PATCH 017/220] move emby-webcomponents to components and reflect paths --- .../actionsheet/actionsheet.css | 0 .../actionsheet/actionsheet.js | 0 .../alert/alert.js | 0 .../alert/nativealert.js | 0 .../alphanumericshortcuts.js | 0 .../alphapicker/alphapicker.js | 0 .../alphapicker/style.css | 0 .../appfooter/appfooter.css | 0 .../appfooter/appfooter.js | 0 .../appsettings.js | 0 .../backdrop/backdrop.js | 0 .../backdrop/style.css | 0 .../browser.js | 0 .../browserdeviceprofile.js | 0 .../cardbuilder/card.css | 0 .../cardbuilder/cardbuilder.js | 0 .../cardbuilder/chaptercardbuilder.js | 0 .../cardbuilder/peoplecardbuilder.js | 0 .../cardbuilder/roundcard.css | 0 .../chromecast/chromecasthelpers.js | 0 .../chromecast/chromecastplayer.js | 0 .../clearbutton.css | 0 .../collectioneditor/collectioneditor.js | 0 .../confirm/confirm.js | 0 .../confirm/nativeconfirm.js | 0 .../datetime.js | 0 .../deletehelper.js | 0 .../dialog/dialog.js | 0 .../dialog/dialog.template.html | 0 .../dialoghelper/dialoghelper.css | 0 .../dialoghelper/dialoghelper.js | 0 .../displaysettings/displaysettings.js | 0 .../displaysettings.template.html | 0 .../emby-webcomponents => components}/dom.js | 0 .../emby-button/emby-button.css | 0 .../emby-button/emby-button.js | 0 .../emby-button/paper-icon-button-light.js | 0 .../emby-checkbox/emby-checkbox.css | 0 .../emby-checkbox/emby-checkbox.js | 0 .../emby-collapse/emby-collapse.css | 0 .../emby-collapse/emby-collapse.js | 0 .../emby-input/emby-input.css | 0 .../emby-input/emby-input.js | 0 .../emby-itemrefreshindicator.js | 0 .../emby-itemscontainer.js | 0 .../emby-progressring/emby-progressring.css | 0 .../emby-progressring/emby-progressring.js | 0 .../emby-progressring.template.html | 0 .../emby-radio/emby-radio.css | 0 .../emby-radio/emby-radio.js | 0 .../emby-scrollbuttons/emby-scrollbuttons.css | 0 .../emby-scrollbuttons/emby-scrollbuttons.js | 0 .../emby-scroller/emby-scroller.js | 0 .../emby-select/emby-select.css | 0 .../emby-select/emby-select.js | 0 .../emby-slider/emby-slider.css | 0 .../emby-slider/emby-slider.js | 0 .../emby-tabs/emby-tabs.css | 0 .../emby-tabs/emby-tabs.js | 0 .../emby-textarea/emby-textarea.css | 0 .../emby-textarea/emby-textarea.js | 0 .../emby-toggle/emby-toggle.css | 0 .../emby-toggle/emby-toggle.js | 0 .../fetchhelper.js | 0 .../filedownloader.js | 0 .../filesystem.js | 0 .../filtermenu/filtermenu.js | 0 .../filtermenu/filtermenu.template.html | 0 .../flexstyles.css | 0 .../flvjs/flv.min.js | 0 .../focusmanager.js | 0 .../fonts/fonts.css | 0 .../fonts/fonts.sized.css | 0 .../flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff | Bin .../flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2 | Bin .../fonts/material-icons/style.css | 0 .../formdialog.css | 0 .../fullscreen/fullscreen-dc.js | 0 .../fullscreen/fullscreenmanager.js | 0 .../globalize.js | 0 .../guide/guide-settings.js | 0 .../guide/guide-settings.template.html | 0 .../guide/guide.css | 0 .../guide/guide.js | 0 .../guide/programs.css | 0 .../guide/tvguide.template.html | 0 .../headroom/headroom.css | 0 .../headroom/headroom.js | 0 .../homescreensettings/homescreensettings.js | 0 .../homescreensettings.template.html | 0 .../homescreensettingsdialog.js | 0 .../homescreensettingsdialog.template.html | 0 .../homesections/homesections.css | 0 .../homesections/homesections.js | 0 .../htmlaudioplayer/plugin.js | 0 .../htmlvideoplayer/htmlmediahelper.js | 0 .../htmlvideoplayer/plugin.js | 0 .../htmlvideoplayer/style.css | 0 .../imagedownloader/imagedownloader.js | 0 .../imagedownloader.template.html | 0 .../imageeditor/imageeditor.css | 0 .../imageeditor/imageeditor.js | 0 .../imageeditor/imageeditor.template.html | 0 .../images/basicimagefetcher.js | 0 .../images/imagehelper.js | 0 .../images/style.css | 0 .../imageuploader/imageuploader.js | 0 .../imageuploader/imageuploader.template.html | 0 .../imageuploader/style.css | 0 .../indicators/indicators.css | 0 .../indicators/indicators.js | 0 .../input/api.js | 0 .../input/gamepadtokey.js | 0 .../input/mouse.js | 0 .../inputmanager.js | 0 .../itemcontextmenu.js | 0 .../itemhelper.js | 0 .../itemidentifier/itemidentifier.js | 0 .../itemidentifier.template.html | 0 .../itemsrefresher.js | 0 .../layoutmanager.js | 0 .../lazyloader/lazyedgehack.css | 0 .../lazyloader-intersectionobserver.js | 0 .../lazyloader/lazyloader-scroll.js | 0 .../listview/listview.css | 0 .../listview/listview.js | 0 .../loading/loader2.gif | Bin .../loading/loading-legacy.css | 0 .../loading/loading-legacy.js | 0 .../loading/loading-lite.css | 0 .../loading/loading-lite.js | 0 .../loadingdialog/loadingdialog.js | 0 .../maintabsmanager.js | 0 .../mediainfo/fresh.png | Bin .../mediainfo/mediainfo.css | 0 .../mediainfo/mediainfo.js | 0 .../mediainfo/rotten.png | Bin .../metadataeditor/metadataeditor.js | 0 .../metadataeditor.template.html | 0 .../metadataeditor/personeditor.js | 0 .../metadataeditor/personeditor.template.html | 0 .../multidownload.js | 0 .../multiselect/multiselect.css | 0 .../multiselect/multiselect.js | 0 .../native-promise-only/lib/npo.src.js | 0 .../native-promise-only/test_adapter.js | 0 .../notifications/badge.png | Bin .../notifications/notificationicon.png | Bin .../notifications/notifications.js | 0 .../nowplayingbar/nowplayingbar.css | 0 .../nowplayingbar/nowplayingbar.js | 0 .../packagemanager.js | 0 .../pagejs/page.js | 0 .../photoplayer/plugin.js | 0 .../playback/autoplaydetect.js | 0 .../playback/brightnessosd.js | 0 .../playback/experimentalwarnings.js | 0 .../playback/iconosd.css | 0 .../playback/mediasession.js | 0 .../playback/nowplayinghelper.js | 0 .../playback/playaccessvalidation.js | 0 .../playback/playbackmanager.js | 0 .../playback/playbackorientation.js | 0 .../playback/playbackvalidation.js | 0 .../playback/playerselection.js | 0 .../playback/playersettingsmenu.js | 0 .../playback/playmethodhelper.js | 0 .../playback/playqueuemanager.js | 0 .../playback/remotecontrolautoplay.js | 0 .../playback/volumeosd.js | 0 .../playbacksettings/playbacksettings.js | 0 .../playbacksettings.template.html | 0 .../playerstats/playerstats.css | 0 .../playerstats/playerstats.js | 0 .../playlisteditor/playlisteditor.js | 0 .../playmenu.js | 0 .../pluginmanager.js | 0 .../polyfills/array.js | 0 .../polyfills/bind.js | 0 .../polyfills/objectassign.js | 0 .../polyfills/raf.js | 0 .../prompt/nativeprompt.js | 0 .../prompt/prompt.js | 0 .../prompt/prompt.template.html | 0 .../qualityoptions.js | 0 .../recordingcreator/empty.png | Bin .../recordingcreator/recordingbutton.js | 0 .../recordingcreator/recordingcreator.css | 0 .../recordingcreator/recordingcreator.js | 0 .../recordingcreator.template.html | 0 .../recordingcreator/recordingeditor.js | 0 .../recordingeditor.template.html | 0 .../recordingcreator/recordingfields.css | 0 .../recordingcreator/recordingfields.js | 0 .../recordingfields.template.html | 0 .../recordingcreator/recordinghelper.js | 0 .../recordingcreator/seriesrecordingeditor.js | 0 .../seriesrecordingeditor.template.html | 0 .../refreshdialog/refreshdialog.js | 0 .../registrationservices.js | 0 .../require/requirecss.js | 2 +- .../require/requiretext.js | 0 .../ResizeObserver.js | 0 .../router.js | 0 .../sanitizefilename.js | 0 .../scroller/smoothscroller.js | 0 .../scrollhelper.js | 0 .../scrollstyles.css | 0 .../search/searchfields.css | 0 .../search/searchfields.js | 0 .../search/searchfields.template.html | 0 .../search/searchresults.js | 0 .../search/searchresults.template.html | 0 .../serverrestartdialog.js | 0 .../serviceworker/notifications.js | 0 .../serviceworker/sync.js | 0 .../sessionplayer.js | 0 .../shell.js | 0 .../shortcuts.js | 0 .../skinmanager.js | 2 +- .../slideshow/slideshow.js | 0 .../slideshow/style.css | 0 .../sortmenu/sortmenu.js | 0 .../sortmenu/sortmenu.template.html | 0 .../staticbackdrops.js | 0 .../subtitleeditor/subtitleeditor.css | 0 .../subtitleeditor/subtitleeditor.js | 0 .../subtitleeditor.template.html | 0 .../subtitleappearancehelper.js | 0 .../subtitlesettings/subtitlesettings.js | 0 .../subtitlesettings.template.html | 0 .../sync/emby-downloadbutton.js | 0 .../sync/sync.js | 0 .../tabbedview/itemstab.js | 0 .../tabbedview/tabbedview.js | 0 .../thememediaplayer.js | 0 .../themes/appletv/theme.css | 0 .../themes/blueradiance/bg.jpg | Bin .../themes/blueradiance/theme.css | 0 .../themes/dark-classic/theme.css | 0 .../themes/dark-green/theme.css | 0 .../themes/dark-red/theme.css | 0 .../themes/dark/theme.css | 0 .../themes/light-blue/theme.css | 0 .../themes/light-classic/theme.css | 0 .../themes/light-green/theme.css | 0 .../themes/light-pink/theme.css | 0 .../themes/light-purple/theme.css | 0 .../themes/light-red/theme.css | 0 .../themes/light/theme.css | 0 .../themes/logodark.png | Bin .../themes/logowhite.png | Bin .../themes/wmc/theme.css | 0 .../toast/toast.css | 0 .../toast/toast.js | 0 .../touchhelper.js | 0 .../upnextdialog/upnextdialog.css | 0 .../upnextdialog/upnextdialog.js | 0 .../userdatabuttons/emby-playstatebutton.js | 0 .../userdatabuttons/emby-ratingbutton.js | 0 .../userdatabuttons/userdatabuttons.css | 0 .../userdatabuttons/userdatabuttons.js | 0 .../usersettings/usersettings.js | 0 .../usersettings/usersettingsbuilder.js | 0 src/components/viewcontainer-lite.js | 2 +- .../viewmanager/viewcontainer-lite.css | 0 .../viewmanager/viewcontainer-lite.js | 0 .../viewmanager/viewmanager.js | 0 .../viewsettings/viewsettings.js | 0 .../viewsettings/viewsettings.template.html | 0 .../visibleinviewport.js | 0 .../youtubeplayer/plugin.js | 0 .../youtubeplayer/style.css | 0 src/scripts/site.js | 32 +++++++++--------- src/serviceworker.js | 2 +- 275 files changed, 20 insertions(+), 20 deletions(-) rename src/{bower_components/emby-webcomponents => components}/actionsheet/actionsheet.css (100%) rename src/{bower_components/emby-webcomponents => components}/actionsheet/actionsheet.js (100%) rename src/{bower_components/emby-webcomponents => components}/alert/alert.js (100%) rename src/{bower_components/emby-webcomponents => components}/alert/nativealert.js (100%) rename src/{bower_components/emby-webcomponents => components}/alphanumericshortcuts/alphanumericshortcuts.js (100%) rename src/{bower_components/emby-webcomponents => components}/alphapicker/alphapicker.js (100%) rename src/{bower_components/emby-webcomponents => components}/alphapicker/style.css (100%) rename src/{bower_components/emby-webcomponents => components}/appfooter/appfooter.css (100%) rename src/{bower_components/emby-webcomponents => components}/appfooter/appfooter.js (100%) rename src/{bower_components/emby-webcomponents => components}/appsettings.js (100%) rename src/{bower_components/emby-webcomponents => components}/backdrop/backdrop.js (100%) rename src/{bower_components/emby-webcomponents => components}/backdrop/style.css (100%) rename src/{bower_components/emby-webcomponents => components}/browser.js (100%) rename src/{bower_components/emby-webcomponents => components}/browserdeviceprofile.js (100%) rename src/{bower_components/emby-webcomponents => components}/cardbuilder/card.css (100%) rename src/{bower_components/emby-webcomponents => components}/cardbuilder/cardbuilder.js (100%) rename src/{bower_components/emby-webcomponents => components}/cardbuilder/chaptercardbuilder.js (100%) rename src/{bower_components/emby-webcomponents => components}/cardbuilder/peoplecardbuilder.js (100%) rename src/{bower_components/emby-webcomponents => components}/cardbuilder/roundcard.css (100%) rename src/{bower_components/emby-webcomponents => components}/chromecast/chromecasthelpers.js (100%) rename src/{bower_components/emby-webcomponents => components}/chromecast/chromecastplayer.js (100%) rename src/{bower_components/emby-webcomponents => components}/clearbutton.css (100%) rename src/{bower_components/emby-webcomponents => components}/collectioneditor/collectioneditor.js (100%) rename src/{bower_components/emby-webcomponents => components}/confirm/confirm.js (100%) rename src/{bower_components/emby-webcomponents => components}/confirm/nativeconfirm.js (100%) rename src/{bower_components/emby-webcomponents => components}/datetime.js (100%) rename src/{bower_components/emby-webcomponents => components}/deletehelper.js (100%) rename src/{bower_components/emby-webcomponents => components}/dialog/dialog.js (100%) rename src/{bower_components/emby-webcomponents => components}/dialog/dialog.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/dialoghelper/dialoghelper.css (100%) rename src/{bower_components/emby-webcomponents => components}/dialoghelper/dialoghelper.js (100%) rename src/{bower_components/emby-webcomponents => components}/displaysettings/displaysettings.js (100%) rename src/{bower_components/emby-webcomponents => components}/displaysettings/displaysettings.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/dom.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-button/emby-button.css (100%) rename src/{bower_components/emby-webcomponents => components}/emby-button/emby-button.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-button/paper-icon-button-light.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-checkbox/emby-checkbox.css (100%) rename src/{bower_components/emby-webcomponents => components}/emby-checkbox/emby-checkbox.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-collapse/emby-collapse.css (100%) rename src/{bower_components/emby-webcomponents => components}/emby-collapse/emby-collapse.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-input/emby-input.css (100%) rename src/{bower_components/emby-webcomponents => components}/emby-input/emby-input.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-itemrefreshindicator/emby-itemrefreshindicator.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-itemscontainer/emby-itemscontainer.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-progressring/emby-progressring.css (100%) rename src/{bower_components/emby-webcomponents => components}/emby-progressring/emby-progressring.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-progressring/emby-progressring.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/emby-radio/emby-radio.css (100%) rename src/{bower_components/emby-webcomponents => components}/emby-radio/emby-radio.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-scrollbuttons/emby-scrollbuttons.css (100%) rename src/{bower_components/emby-webcomponents => components}/emby-scrollbuttons/emby-scrollbuttons.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-scroller/emby-scroller.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-select/emby-select.css (100%) rename src/{bower_components/emby-webcomponents => components}/emby-select/emby-select.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-slider/emby-slider.css (100%) rename src/{bower_components/emby-webcomponents => components}/emby-slider/emby-slider.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-tabs/emby-tabs.css (100%) rename src/{bower_components/emby-webcomponents => components}/emby-tabs/emby-tabs.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-textarea/emby-textarea.css (100%) rename src/{bower_components/emby-webcomponents => components}/emby-textarea/emby-textarea.js (100%) rename src/{bower_components/emby-webcomponents => components}/emby-toggle/emby-toggle.css (100%) rename src/{bower_components/emby-webcomponents => components}/emby-toggle/emby-toggle.js (100%) rename src/{bower_components/emby-webcomponents => components}/fetchhelper.js (100%) rename src/{bower_components/emby-webcomponents => components}/filedownloader.js (100%) rename src/{bower_components/emby-webcomponents => components}/filesystem.js (100%) rename src/{bower_components/emby-webcomponents => components}/filtermenu/filtermenu.js (100%) rename src/{bower_components/emby-webcomponents => components}/filtermenu/filtermenu.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/flexstyles.css (100%) rename src/{bower_components/emby-webcomponents => components}/flvjs/flv.min.js (100%) rename src/{bower_components/emby-webcomponents => components}/focusmanager.js (100%) rename src/{bower_components/emby-webcomponents => components}/fonts/fonts.css (100%) rename src/{bower_components/emby-webcomponents => components}/fonts/fonts.sized.css (100%) rename src/{bower_components/emby-webcomponents => components}/fonts/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff (100%) rename src/{bower_components/emby-webcomponents => components}/fonts/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2 (100%) rename src/{bower_components/emby-webcomponents => components}/fonts/material-icons/style.css (100%) rename src/{bower_components/emby-webcomponents => components}/formdialog.css (100%) rename src/{bower_components/emby-webcomponents => components}/fullscreen/fullscreen-dc.js (100%) rename src/{bower_components/emby-webcomponents => components}/fullscreen/fullscreenmanager.js (100%) rename src/{bower_components/emby-webcomponents => components}/globalize.js (100%) rename src/{bower_components/emby-webcomponents => components}/guide/guide-settings.js (100%) rename src/{bower_components/emby-webcomponents => components}/guide/guide-settings.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/guide/guide.css (100%) rename src/{bower_components/emby-webcomponents => components}/guide/guide.js (100%) rename src/{bower_components/emby-webcomponents => components}/guide/programs.css (100%) rename src/{bower_components/emby-webcomponents => components}/guide/tvguide.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/headroom/headroom.css (100%) rename src/{bower_components/emby-webcomponents => components}/headroom/headroom.js (100%) rename src/{bower_components/emby-webcomponents => components}/homescreensettings/homescreensettings.js (100%) rename src/{bower_components/emby-webcomponents => components}/homescreensettings/homescreensettings.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/homescreensettings/homescreensettingsdialog.js (100%) rename src/{bower_components/emby-webcomponents => components}/homescreensettings/homescreensettingsdialog.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/homesections/homesections.css (100%) rename src/{bower_components/emby-webcomponents => components}/homesections/homesections.js (100%) rename src/{bower_components/emby-webcomponents => components}/htmlaudioplayer/plugin.js (100%) rename src/{bower_components/emby-webcomponents => components}/htmlvideoplayer/htmlmediahelper.js (100%) rename src/{bower_components/emby-webcomponents => components}/htmlvideoplayer/plugin.js (100%) rename src/{bower_components/emby-webcomponents => components}/htmlvideoplayer/style.css (100%) rename src/{bower_components/emby-webcomponents => components}/imagedownloader/imagedownloader.js (100%) rename src/{bower_components/emby-webcomponents => components}/imagedownloader/imagedownloader.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/imageeditor/imageeditor.css (100%) rename src/{bower_components/emby-webcomponents => components}/imageeditor/imageeditor.js (100%) rename src/{bower_components/emby-webcomponents => components}/imageeditor/imageeditor.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/images/basicimagefetcher.js (100%) rename src/{bower_components/emby-webcomponents => components}/images/imagehelper.js (100%) rename src/{bower_components/emby-webcomponents => components}/images/style.css (100%) rename src/{bower_components/emby-webcomponents => components}/imageuploader/imageuploader.js (100%) rename src/{bower_components/emby-webcomponents => components}/imageuploader/imageuploader.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/imageuploader/style.css (100%) rename src/{bower_components/emby-webcomponents => components}/indicators/indicators.css (100%) rename src/{bower_components/emby-webcomponents => components}/indicators/indicators.js (100%) rename src/{bower_components/emby-webcomponents => components}/input/api.js (100%) rename src/{bower_components/emby-webcomponents => components}/input/gamepadtokey.js (100%) rename src/{bower_components/emby-webcomponents => components}/input/mouse.js (100%) rename src/{bower_components/emby-webcomponents => components}/inputmanager.js (100%) rename src/{bower_components/emby-webcomponents => components}/itemcontextmenu.js (100%) rename src/{bower_components/emby-webcomponents => components}/itemhelper.js (100%) rename src/{bower_components/emby-webcomponents => components}/itemidentifier/itemidentifier.js (100%) rename src/{bower_components/emby-webcomponents => components}/itemidentifier/itemidentifier.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/itemsrefresher.js (100%) rename src/{bower_components/emby-webcomponents => components}/layoutmanager.js (100%) rename src/{bower_components/emby-webcomponents => components}/lazyloader/lazyedgehack.css (100%) rename src/{bower_components/emby-webcomponents => components}/lazyloader/lazyloader-intersectionobserver.js (100%) rename src/{bower_components/emby-webcomponents => components}/lazyloader/lazyloader-scroll.js (100%) rename src/{bower_components/emby-webcomponents => components}/listview/listview.css (100%) rename src/{bower_components/emby-webcomponents => components}/listview/listview.js (100%) rename src/{bower_components/emby-webcomponents => components}/loading/loader2.gif (100%) rename src/{bower_components/emby-webcomponents => components}/loading/loading-legacy.css (100%) rename src/{bower_components/emby-webcomponents => components}/loading/loading-legacy.js (100%) rename src/{bower_components/emby-webcomponents => components}/loading/loading-lite.css (100%) rename src/{bower_components/emby-webcomponents => components}/loading/loading-lite.js (100%) rename src/{bower_components/emby-webcomponents => components}/loadingdialog/loadingdialog.js (100%) rename src/{bower_components/emby-webcomponents => components}/maintabsmanager.js (100%) rename src/{bower_components/emby-webcomponents => components}/mediainfo/fresh.png (100%) rename src/{bower_components/emby-webcomponents => components}/mediainfo/mediainfo.css (100%) rename src/{bower_components/emby-webcomponents => components}/mediainfo/mediainfo.js (100%) rename src/{bower_components/emby-webcomponents => components}/mediainfo/rotten.png (100%) rename src/{bower_components/emby-webcomponents => components}/metadataeditor/metadataeditor.js (100%) rename src/{bower_components/emby-webcomponents => components}/metadataeditor/metadataeditor.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/metadataeditor/personeditor.js (100%) rename src/{bower_components/emby-webcomponents => components}/metadataeditor/personeditor.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/multidownload.js (100%) rename src/{bower_components/emby-webcomponents => components}/multiselect/multiselect.css (100%) rename src/{bower_components/emby-webcomponents => components}/multiselect/multiselect.js (100%) rename src/{bower_components/emby-webcomponents => components}/native-promise-only/lib/npo.src.js (100%) rename src/{bower_components/emby-webcomponents => components}/native-promise-only/test_adapter.js (100%) rename src/{bower_components/emby-webcomponents => components}/notifications/badge.png (100%) rename src/{bower_components/emby-webcomponents => components}/notifications/notificationicon.png (100%) rename src/{bower_components/emby-webcomponents => components}/notifications/notifications.js (100%) rename src/{bower_components/emby-webcomponents => components}/nowplayingbar/nowplayingbar.css (100%) rename src/{bower_components/emby-webcomponents => components}/nowplayingbar/nowplayingbar.js (100%) rename src/{bower_components/emby-webcomponents => components}/packagemanager.js (100%) rename src/{bower_components/emby-webcomponents => components}/pagejs/page.js (100%) rename src/{bower_components/emby-webcomponents => components}/photoplayer/plugin.js (100%) rename src/{bower_components/emby-webcomponents => components}/playback/autoplaydetect.js (100%) rename src/{bower_components/emby-webcomponents => components}/playback/brightnessosd.js (100%) rename src/{bower_components/emby-webcomponents => components}/playback/experimentalwarnings.js (100%) rename src/{bower_components/emby-webcomponents => components}/playback/iconosd.css (100%) rename src/{bower_components/emby-webcomponents => components}/playback/mediasession.js (100%) rename src/{bower_components/emby-webcomponents => components}/playback/nowplayinghelper.js (100%) rename src/{bower_components/emby-webcomponents => components}/playback/playaccessvalidation.js (100%) rename src/{bower_components/emby-webcomponents => components}/playback/playbackmanager.js (100%) rename src/{bower_components/emby-webcomponents => components}/playback/playbackorientation.js (100%) rename src/{bower_components/emby-webcomponents => components}/playback/playbackvalidation.js (100%) rename src/{bower_components/emby-webcomponents => components}/playback/playerselection.js (100%) rename src/{bower_components/emby-webcomponents => components}/playback/playersettingsmenu.js (100%) rename src/{bower_components/emby-webcomponents => components}/playback/playmethodhelper.js (100%) rename src/{bower_components/emby-webcomponents => components}/playback/playqueuemanager.js (100%) rename src/{bower_components/emby-webcomponents => components}/playback/remotecontrolautoplay.js (100%) rename src/{bower_components/emby-webcomponents => components}/playback/volumeosd.js (100%) rename src/{bower_components/emby-webcomponents => components}/playbacksettings/playbacksettings.js (100%) rename src/{bower_components/emby-webcomponents => components}/playbacksettings/playbacksettings.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/playerstats/playerstats.css (100%) rename src/{bower_components/emby-webcomponents => components}/playerstats/playerstats.js (100%) rename src/{bower_components/emby-webcomponents => components}/playlisteditor/playlisteditor.js (100%) rename src/{bower_components/emby-webcomponents => components}/playmenu.js (100%) rename src/{bower_components/emby-webcomponents => components}/pluginmanager.js (100%) rename src/{bower_components/emby-webcomponents => components}/polyfills/array.js (100%) rename src/{bower_components/emby-webcomponents => components}/polyfills/bind.js (100%) rename src/{bower_components/emby-webcomponents => components}/polyfills/objectassign.js (100%) rename src/{bower_components/emby-webcomponents => components}/polyfills/raf.js (100%) rename src/{bower_components/emby-webcomponents => components}/prompt/nativeprompt.js (100%) rename src/{bower_components/emby-webcomponents => components}/prompt/prompt.js (100%) rename src/{bower_components/emby-webcomponents => components}/prompt/prompt.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/qualityoptions.js (100%) rename src/{bower_components/emby-webcomponents => components}/recordingcreator/empty.png (100%) rename src/{bower_components/emby-webcomponents => components}/recordingcreator/recordingbutton.js (100%) rename src/{bower_components/emby-webcomponents => components}/recordingcreator/recordingcreator.css (100%) rename src/{bower_components/emby-webcomponents => components}/recordingcreator/recordingcreator.js (100%) rename src/{bower_components/emby-webcomponents => components}/recordingcreator/recordingcreator.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/recordingcreator/recordingeditor.js (100%) rename src/{bower_components/emby-webcomponents => components}/recordingcreator/recordingeditor.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/recordingcreator/recordingfields.css (100%) rename src/{bower_components/emby-webcomponents => components}/recordingcreator/recordingfields.js (100%) rename src/{bower_components/emby-webcomponents => components}/recordingcreator/recordingfields.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/recordingcreator/recordinghelper.js (100%) rename src/{bower_components/emby-webcomponents => components}/recordingcreator/seriesrecordingeditor.js (100%) rename src/{bower_components/emby-webcomponents => components}/recordingcreator/seriesrecordingeditor.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/refreshdialog/refreshdialog.js (100%) rename src/{bower_components/emby-webcomponents => components}/registrationservices/registrationservices.js (100%) rename src/{bower_components/emby-webcomponents => components}/require/requirecss.js (96%) rename src/{bower_components/emby-webcomponents => components}/require/requiretext.js (100%) rename src/{bower_components/emby-webcomponents => components}/resize-observer-polyfill/ResizeObserver.js (100%) rename src/{bower_components/emby-webcomponents => components}/router.js (100%) rename src/{bower_components/emby-webcomponents => components}/sanitizefilename.js (100%) rename src/{bower_components/emby-webcomponents => components}/scroller/smoothscroller.js (100%) rename src/{bower_components/emby-webcomponents => components}/scrollhelper.js (100%) rename src/{bower_components/emby-webcomponents => components}/scrollstyles.css (100%) rename src/{bower_components/emby-webcomponents => components}/search/searchfields.css (100%) rename src/{bower_components/emby-webcomponents => components}/search/searchfields.js (100%) rename src/{bower_components/emby-webcomponents => components}/search/searchfields.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/search/searchresults.js (100%) rename src/{bower_components/emby-webcomponents => components}/search/searchresults.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/serverrestartdialog/serverrestartdialog.js (100%) rename src/{bower_components/emby-webcomponents => components}/serviceworker/notifications.js (100%) rename src/{bower_components/emby-webcomponents => components}/serviceworker/sync.js (100%) rename src/{bower_components/emby-webcomponents => components}/sessionplayer.js (100%) rename src/{bower_components/emby-webcomponents => components}/shell.js (100%) rename src/{bower_components/emby-webcomponents => components}/shortcuts.js (100%) rename src/{bower_components/emby-webcomponents => components}/skinmanager.js (99%) rename src/{bower_components/emby-webcomponents => components}/slideshow/slideshow.js (100%) rename src/{bower_components/emby-webcomponents => components}/slideshow/style.css (100%) rename src/{bower_components/emby-webcomponents => components}/sortmenu/sortmenu.js (100%) rename src/{bower_components/emby-webcomponents => components}/sortmenu/sortmenu.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/staticbackdrops.js (100%) rename src/{bower_components/emby-webcomponents => components}/subtitleeditor/subtitleeditor.css (100%) rename src/{bower_components/emby-webcomponents => components}/subtitleeditor/subtitleeditor.js (100%) rename src/{bower_components/emby-webcomponents => components}/subtitleeditor/subtitleeditor.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/subtitlesettings/subtitleappearancehelper.js (100%) rename src/{bower_components/emby-webcomponents => components}/subtitlesettings/subtitlesettings.js (100%) rename src/{bower_components/emby-webcomponents => components}/subtitlesettings/subtitlesettings.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/sync/emby-downloadbutton.js (100%) rename src/{bower_components/emby-webcomponents => components}/sync/sync.js (100%) rename src/{bower_components/emby-webcomponents => components}/tabbedview/itemstab.js (100%) rename src/{bower_components/emby-webcomponents => components}/tabbedview/tabbedview.js (100%) rename src/{bower_components/emby-webcomponents => components}/thememediaplayer.js (100%) rename src/{bower_components/emby-webcomponents => components}/themes/appletv/theme.css (100%) rename src/{bower_components/emby-webcomponents => components}/themes/blueradiance/bg.jpg (100%) rename src/{bower_components/emby-webcomponents => components}/themes/blueradiance/theme.css (100%) rename src/{bower_components/emby-webcomponents => components}/themes/dark-classic/theme.css (100%) rename src/{bower_components/emby-webcomponents => components}/themes/dark-green/theme.css (100%) rename src/{bower_components/emby-webcomponents => components}/themes/dark-red/theme.css (100%) rename src/{bower_components/emby-webcomponents => components}/themes/dark/theme.css (100%) rename src/{bower_components/emby-webcomponents => components}/themes/light-blue/theme.css (100%) rename src/{bower_components/emby-webcomponents => components}/themes/light-classic/theme.css (100%) rename src/{bower_components/emby-webcomponents => components}/themes/light-green/theme.css (100%) rename src/{bower_components/emby-webcomponents => components}/themes/light-pink/theme.css (100%) rename src/{bower_components/emby-webcomponents => components}/themes/light-purple/theme.css (100%) rename src/{bower_components/emby-webcomponents => components}/themes/light-red/theme.css (100%) rename src/{bower_components/emby-webcomponents => components}/themes/light/theme.css (100%) rename src/{bower_components/emby-webcomponents => components}/themes/logodark.png (100%) rename src/{bower_components/emby-webcomponents => components}/themes/logowhite.png (100%) rename src/{bower_components/emby-webcomponents => components}/themes/wmc/theme.css (100%) rename src/{bower_components/emby-webcomponents => components}/toast/toast.css (100%) rename src/{bower_components/emby-webcomponents => components}/toast/toast.js (100%) rename src/{bower_components/emby-webcomponents => components}/touchhelper.js (100%) rename src/{bower_components/emby-webcomponents => components}/upnextdialog/upnextdialog.css (100%) rename src/{bower_components/emby-webcomponents => components}/upnextdialog/upnextdialog.js (100%) rename src/{bower_components/emby-webcomponents => components}/userdatabuttons/emby-playstatebutton.js (100%) rename src/{bower_components/emby-webcomponents => components}/userdatabuttons/emby-ratingbutton.js (100%) rename src/{bower_components/emby-webcomponents => components}/userdatabuttons/userdatabuttons.css (100%) rename src/{bower_components/emby-webcomponents => components}/userdatabuttons/userdatabuttons.js (100%) rename src/{bower_components/emby-webcomponents => components}/usersettings/usersettings.js (100%) rename src/{bower_components/emby-webcomponents => components}/usersettings/usersettingsbuilder.js (100%) rename src/{bower_components/emby-webcomponents => components}/viewmanager/viewcontainer-lite.css (100%) rename src/{bower_components/emby-webcomponents => components}/viewmanager/viewcontainer-lite.js (100%) rename src/{bower_components/emby-webcomponents => components}/viewmanager/viewmanager.js (100%) rename src/{bower_components/emby-webcomponents => components}/viewsettings/viewsettings.js (100%) rename src/{bower_components/emby-webcomponents => components}/viewsettings/viewsettings.template.html (100%) rename src/{bower_components/emby-webcomponents => components}/visibleinviewport.js (100%) rename src/{bower_components/emby-webcomponents => components}/youtubeplayer/plugin.js (100%) rename src/{bower_components/emby-webcomponents => components}/youtubeplayer/style.css (100%) diff --git a/src/bower_components/emby-webcomponents/actionsheet/actionsheet.css b/src/components/actionsheet/actionsheet.css similarity index 100% rename from src/bower_components/emby-webcomponents/actionsheet/actionsheet.css rename to src/components/actionsheet/actionsheet.css diff --git a/src/bower_components/emby-webcomponents/actionsheet/actionsheet.js b/src/components/actionsheet/actionsheet.js similarity index 100% rename from src/bower_components/emby-webcomponents/actionsheet/actionsheet.js rename to src/components/actionsheet/actionsheet.js diff --git a/src/bower_components/emby-webcomponents/alert/alert.js b/src/components/alert/alert.js similarity index 100% rename from src/bower_components/emby-webcomponents/alert/alert.js rename to src/components/alert/alert.js diff --git a/src/bower_components/emby-webcomponents/alert/nativealert.js b/src/components/alert/nativealert.js similarity index 100% rename from src/bower_components/emby-webcomponents/alert/nativealert.js rename to src/components/alert/nativealert.js diff --git a/src/bower_components/emby-webcomponents/alphanumericshortcuts/alphanumericshortcuts.js b/src/components/alphanumericshortcuts/alphanumericshortcuts.js similarity index 100% rename from src/bower_components/emby-webcomponents/alphanumericshortcuts/alphanumericshortcuts.js rename to src/components/alphanumericshortcuts/alphanumericshortcuts.js diff --git a/src/bower_components/emby-webcomponents/alphapicker/alphapicker.js b/src/components/alphapicker/alphapicker.js similarity index 100% rename from src/bower_components/emby-webcomponents/alphapicker/alphapicker.js rename to src/components/alphapicker/alphapicker.js diff --git a/src/bower_components/emby-webcomponents/alphapicker/style.css b/src/components/alphapicker/style.css similarity index 100% rename from src/bower_components/emby-webcomponents/alphapicker/style.css rename to src/components/alphapicker/style.css diff --git a/src/bower_components/emby-webcomponents/appfooter/appfooter.css b/src/components/appfooter/appfooter.css similarity index 100% rename from src/bower_components/emby-webcomponents/appfooter/appfooter.css rename to src/components/appfooter/appfooter.css diff --git a/src/bower_components/emby-webcomponents/appfooter/appfooter.js b/src/components/appfooter/appfooter.js similarity index 100% rename from src/bower_components/emby-webcomponents/appfooter/appfooter.js rename to src/components/appfooter/appfooter.js diff --git a/src/bower_components/emby-webcomponents/appsettings.js b/src/components/appsettings.js similarity index 100% rename from src/bower_components/emby-webcomponents/appsettings.js rename to src/components/appsettings.js diff --git a/src/bower_components/emby-webcomponents/backdrop/backdrop.js b/src/components/backdrop/backdrop.js similarity index 100% rename from src/bower_components/emby-webcomponents/backdrop/backdrop.js rename to src/components/backdrop/backdrop.js diff --git a/src/bower_components/emby-webcomponents/backdrop/style.css b/src/components/backdrop/style.css similarity index 100% rename from src/bower_components/emby-webcomponents/backdrop/style.css rename to src/components/backdrop/style.css diff --git a/src/bower_components/emby-webcomponents/browser.js b/src/components/browser.js similarity index 100% rename from src/bower_components/emby-webcomponents/browser.js rename to src/components/browser.js diff --git a/src/bower_components/emby-webcomponents/browserdeviceprofile.js b/src/components/browserdeviceprofile.js similarity index 100% rename from src/bower_components/emby-webcomponents/browserdeviceprofile.js rename to src/components/browserdeviceprofile.js diff --git a/src/bower_components/emby-webcomponents/cardbuilder/card.css b/src/components/cardbuilder/card.css similarity index 100% rename from src/bower_components/emby-webcomponents/cardbuilder/card.css rename to src/components/cardbuilder/card.css diff --git a/src/bower_components/emby-webcomponents/cardbuilder/cardbuilder.js b/src/components/cardbuilder/cardbuilder.js similarity index 100% rename from src/bower_components/emby-webcomponents/cardbuilder/cardbuilder.js rename to src/components/cardbuilder/cardbuilder.js diff --git a/src/bower_components/emby-webcomponents/cardbuilder/chaptercardbuilder.js b/src/components/cardbuilder/chaptercardbuilder.js similarity index 100% rename from src/bower_components/emby-webcomponents/cardbuilder/chaptercardbuilder.js rename to src/components/cardbuilder/chaptercardbuilder.js diff --git a/src/bower_components/emby-webcomponents/cardbuilder/peoplecardbuilder.js b/src/components/cardbuilder/peoplecardbuilder.js similarity index 100% rename from src/bower_components/emby-webcomponents/cardbuilder/peoplecardbuilder.js rename to src/components/cardbuilder/peoplecardbuilder.js diff --git a/src/bower_components/emby-webcomponents/cardbuilder/roundcard.css b/src/components/cardbuilder/roundcard.css similarity index 100% rename from src/bower_components/emby-webcomponents/cardbuilder/roundcard.css rename to src/components/cardbuilder/roundcard.css diff --git a/src/bower_components/emby-webcomponents/chromecast/chromecasthelpers.js b/src/components/chromecast/chromecasthelpers.js similarity index 100% rename from src/bower_components/emby-webcomponents/chromecast/chromecasthelpers.js rename to src/components/chromecast/chromecasthelpers.js diff --git a/src/bower_components/emby-webcomponents/chromecast/chromecastplayer.js b/src/components/chromecast/chromecastplayer.js similarity index 100% rename from src/bower_components/emby-webcomponents/chromecast/chromecastplayer.js rename to src/components/chromecast/chromecastplayer.js diff --git a/src/bower_components/emby-webcomponents/clearbutton.css b/src/components/clearbutton.css similarity index 100% rename from src/bower_components/emby-webcomponents/clearbutton.css rename to src/components/clearbutton.css diff --git a/src/bower_components/emby-webcomponents/collectioneditor/collectioneditor.js b/src/components/collectioneditor/collectioneditor.js similarity index 100% rename from src/bower_components/emby-webcomponents/collectioneditor/collectioneditor.js rename to src/components/collectioneditor/collectioneditor.js diff --git a/src/bower_components/emby-webcomponents/confirm/confirm.js b/src/components/confirm/confirm.js similarity index 100% rename from src/bower_components/emby-webcomponents/confirm/confirm.js rename to src/components/confirm/confirm.js diff --git a/src/bower_components/emby-webcomponents/confirm/nativeconfirm.js b/src/components/confirm/nativeconfirm.js similarity index 100% rename from src/bower_components/emby-webcomponents/confirm/nativeconfirm.js rename to src/components/confirm/nativeconfirm.js diff --git a/src/bower_components/emby-webcomponents/datetime.js b/src/components/datetime.js similarity index 100% rename from src/bower_components/emby-webcomponents/datetime.js rename to src/components/datetime.js diff --git a/src/bower_components/emby-webcomponents/deletehelper.js b/src/components/deletehelper.js similarity index 100% rename from src/bower_components/emby-webcomponents/deletehelper.js rename to src/components/deletehelper.js diff --git a/src/bower_components/emby-webcomponents/dialog/dialog.js b/src/components/dialog/dialog.js similarity index 100% rename from src/bower_components/emby-webcomponents/dialog/dialog.js rename to src/components/dialog/dialog.js diff --git a/src/bower_components/emby-webcomponents/dialog/dialog.template.html b/src/components/dialog/dialog.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/dialog/dialog.template.html rename to src/components/dialog/dialog.template.html diff --git a/src/bower_components/emby-webcomponents/dialoghelper/dialoghelper.css b/src/components/dialoghelper/dialoghelper.css similarity index 100% rename from src/bower_components/emby-webcomponents/dialoghelper/dialoghelper.css rename to src/components/dialoghelper/dialoghelper.css diff --git a/src/bower_components/emby-webcomponents/dialoghelper/dialoghelper.js b/src/components/dialoghelper/dialoghelper.js similarity index 100% rename from src/bower_components/emby-webcomponents/dialoghelper/dialoghelper.js rename to src/components/dialoghelper/dialoghelper.js diff --git a/src/bower_components/emby-webcomponents/displaysettings/displaysettings.js b/src/components/displaysettings/displaysettings.js similarity index 100% rename from src/bower_components/emby-webcomponents/displaysettings/displaysettings.js rename to src/components/displaysettings/displaysettings.js diff --git a/src/bower_components/emby-webcomponents/displaysettings/displaysettings.template.html b/src/components/displaysettings/displaysettings.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/displaysettings/displaysettings.template.html rename to src/components/displaysettings/displaysettings.template.html diff --git a/src/bower_components/emby-webcomponents/dom.js b/src/components/dom.js similarity index 100% rename from src/bower_components/emby-webcomponents/dom.js rename to src/components/dom.js diff --git a/src/bower_components/emby-webcomponents/emby-button/emby-button.css b/src/components/emby-button/emby-button.css similarity index 100% rename from src/bower_components/emby-webcomponents/emby-button/emby-button.css rename to src/components/emby-button/emby-button.css diff --git a/src/bower_components/emby-webcomponents/emby-button/emby-button.js b/src/components/emby-button/emby-button.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-button/emby-button.js rename to src/components/emby-button/emby-button.js diff --git a/src/bower_components/emby-webcomponents/emby-button/paper-icon-button-light.js b/src/components/emby-button/paper-icon-button-light.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-button/paper-icon-button-light.js rename to src/components/emby-button/paper-icon-button-light.js diff --git a/src/bower_components/emby-webcomponents/emby-checkbox/emby-checkbox.css b/src/components/emby-checkbox/emby-checkbox.css similarity index 100% rename from src/bower_components/emby-webcomponents/emby-checkbox/emby-checkbox.css rename to src/components/emby-checkbox/emby-checkbox.css diff --git a/src/bower_components/emby-webcomponents/emby-checkbox/emby-checkbox.js b/src/components/emby-checkbox/emby-checkbox.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-checkbox/emby-checkbox.js rename to src/components/emby-checkbox/emby-checkbox.js diff --git a/src/bower_components/emby-webcomponents/emby-collapse/emby-collapse.css b/src/components/emby-collapse/emby-collapse.css similarity index 100% rename from src/bower_components/emby-webcomponents/emby-collapse/emby-collapse.css rename to src/components/emby-collapse/emby-collapse.css diff --git a/src/bower_components/emby-webcomponents/emby-collapse/emby-collapse.js b/src/components/emby-collapse/emby-collapse.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-collapse/emby-collapse.js rename to src/components/emby-collapse/emby-collapse.js diff --git a/src/bower_components/emby-webcomponents/emby-input/emby-input.css b/src/components/emby-input/emby-input.css similarity index 100% rename from src/bower_components/emby-webcomponents/emby-input/emby-input.css rename to src/components/emby-input/emby-input.css diff --git a/src/bower_components/emby-webcomponents/emby-input/emby-input.js b/src/components/emby-input/emby-input.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-input/emby-input.js rename to src/components/emby-input/emby-input.js diff --git a/src/bower_components/emby-webcomponents/emby-itemrefreshindicator/emby-itemrefreshindicator.js b/src/components/emby-itemrefreshindicator/emby-itemrefreshindicator.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-itemrefreshindicator/emby-itemrefreshindicator.js rename to src/components/emby-itemrefreshindicator/emby-itemrefreshindicator.js diff --git a/src/bower_components/emby-webcomponents/emby-itemscontainer/emby-itemscontainer.js b/src/components/emby-itemscontainer/emby-itemscontainer.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-itemscontainer/emby-itemscontainer.js rename to src/components/emby-itemscontainer/emby-itemscontainer.js diff --git a/src/bower_components/emby-webcomponents/emby-progressring/emby-progressring.css b/src/components/emby-progressring/emby-progressring.css similarity index 100% rename from src/bower_components/emby-webcomponents/emby-progressring/emby-progressring.css rename to src/components/emby-progressring/emby-progressring.css diff --git a/src/bower_components/emby-webcomponents/emby-progressring/emby-progressring.js b/src/components/emby-progressring/emby-progressring.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-progressring/emby-progressring.js rename to src/components/emby-progressring/emby-progressring.js diff --git a/src/bower_components/emby-webcomponents/emby-progressring/emby-progressring.template.html b/src/components/emby-progressring/emby-progressring.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/emby-progressring/emby-progressring.template.html rename to src/components/emby-progressring/emby-progressring.template.html diff --git a/src/bower_components/emby-webcomponents/emby-radio/emby-radio.css b/src/components/emby-radio/emby-radio.css similarity index 100% rename from src/bower_components/emby-webcomponents/emby-radio/emby-radio.css rename to src/components/emby-radio/emby-radio.css diff --git a/src/bower_components/emby-webcomponents/emby-radio/emby-radio.js b/src/components/emby-radio/emby-radio.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-radio/emby-radio.js rename to src/components/emby-radio/emby-radio.js diff --git a/src/bower_components/emby-webcomponents/emby-scrollbuttons/emby-scrollbuttons.css b/src/components/emby-scrollbuttons/emby-scrollbuttons.css similarity index 100% rename from src/bower_components/emby-webcomponents/emby-scrollbuttons/emby-scrollbuttons.css rename to src/components/emby-scrollbuttons/emby-scrollbuttons.css diff --git a/src/bower_components/emby-webcomponents/emby-scrollbuttons/emby-scrollbuttons.js b/src/components/emby-scrollbuttons/emby-scrollbuttons.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-scrollbuttons/emby-scrollbuttons.js rename to src/components/emby-scrollbuttons/emby-scrollbuttons.js diff --git a/src/bower_components/emby-webcomponents/emby-scroller/emby-scroller.js b/src/components/emby-scroller/emby-scroller.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-scroller/emby-scroller.js rename to src/components/emby-scroller/emby-scroller.js diff --git a/src/bower_components/emby-webcomponents/emby-select/emby-select.css b/src/components/emby-select/emby-select.css similarity index 100% rename from src/bower_components/emby-webcomponents/emby-select/emby-select.css rename to src/components/emby-select/emby-select.css diff --git a/src/bower_components/emby-webcomponents/emby-select/emby-select.js b/src/components/emby-select/emby-select.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-select/emby-select.js rename to src/components/emby-select/emby-select.js diff --git a/src/bower_components/emby-webcomponents/emby-slider/emby-slider.css b/src/components/emby-slider/emby-slider.css similarity index 100% rename from src/bower_components/emby-webcomponents/emby-slider/emby-slider.css rename to src/components/emby-slider/emby-slider.css diff --git a/src/bower_components/emby-webcomponents/emby-slider/emby-slider.js b/src/components/emby-slider/emby-slider.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-slider/emby-slider.js rename to src/components/emby-slider/emby-slider.js diff --git a/src/bower_components/emby-webcomponents/emby-tabs/emby-tabs.css b/src/components/emby-tabs/emby-tabs.css similarity index 100% rename from src/bower_components/emby-webcomponents/emby-tabs/emby-tabs.css rename to src/components/emby-tabs/emby-tabs.css diff --git a/src/bower_components/emby-webcomponents/emby-tabs/emby-tabs.js b/src/components/emby-tabs/emby-tabs.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-tabs/emby-tabs.js rename to src/components/emby-tabs/emby-tabs.js diff --git a/src/bower_components/emby-webcomponents/emby-textarea/emby-textarea.css b/src/components/emby-textarea/emby-textarea.css similarity index 100% rename from src/bower_components/emby-webcomponents/emby-textarea/emby-textarea.css rename to src/components/emby-textarea/emby-textarea.css diff --git a/src/bower_components/emby-webcomponents/emby-textarea/emby-textarea.js b/src/components/emby-textarea/emby-textarea.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-textarea/emby-textarea.js rename to src/components/emby-textarea/emby-textarea.js diff --git a/src/bower_components/emby-webcomponents/emby-toggle/emby-toggle.css b/src/components/emby-toggle/emby-toggle.css similarity index 100% rename from src/bower_components/emby-webcomponents/emby-toggle/emby-toggle.css rename to src/components/emby-toggle/emby-toggle.css diff --git a/src/bower_components/emby-webcomponents/emby-toggle/emby-toggle.js b/src/components/emby-toggle/emby-toggle.js similarity index 100% rename from src/bower_components/emby-webcomponents/emby-toggle/emby-toggle.js rename to src/components/emby-toggle/emby-toggle.js diff --git a/src/bower_components/emby-webcomponents/fetchhelper.js b/src/components/fetchhelper.js similarity index 100% rename from src/bower_components/emby-webcomponents/fetchhelper.js rename to src/components/fetchhelper.js diff --git a/src/bower_components/emby-webcomponents/filedownloader.js b/src/components/filedownloader.js similarity index 100% rename from src/bower_components/emby-webcomponents/filedownloader.js rename to src/components/filedownloader.js diff --git a/src/bower_components/emby-webcomponents/filesystem.js b/src/components/filesystem.js similarity index 100% rename from src/bower_components/emby-webcomponents/filesystem.js rename to src/components/filesystem.js diff --git a/src/bower_components/emby-webcomponents/filtermenu/filtermenu.js b/src/components/filtermenu/filtermenu.js similarity index 100% rename from src/bower_components/emby-webcomponents/filtermenu/filtermenu.js rename to src/components/filtermenu/filtermenu.js diff --git a/src/bower_components/emby-webcomponents/filtermenu/filtermenu.template.html b/src/components/filtermenu/filtermenu.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/filtermenu/filtermenu.template.html rename to src/components/filtermenu/filtermenu.template.html diff --git a/src/bower_components/emby-webcomponents/flexstyles.css b/src/components/flexstyles.css similarity index 100% rename from src/bower_components/emby-webcomponents/flexstyles.css rename to src/components/flexstyles.css diff --git a/src/bower_components/emby-webcomponents/flvjs/flv.min.js b/src/components/flvjs/flv.min.js similarity index 100% rename from src/bower_components/emby-webcomponents/flvjs/flv.min.js rename to src/components/flvjs/flv.min.js diff --git a/src/bower_components/emby-webcomponents/focusmanager.js b/src/components/focusmanager.js similarity index 100% rename from src/bower_components/emby-webcomponents/focusmanager.js rename to src/components/focusmanager.js diff --git a/src/bower_components/emby-webcomponents/fonts/fonts.css b/src/components/fonts/fonts.css similarity index 100% rename from src/bower_components/emby-webcomponents/fonts/fonts.css rename to src/components/fonts/fonts.css diff --git a/src/bower_components/emby-webcomponents/fonts/fonts.sized.css b/src/components/fonts/fonts.sized.css similarity index 100% rename from src/bower_components/emby-webcomponents/fonts/fonts.sized.css rename to src/components/fonts/fonts.sized.css diff --git a/src/bower_components/emby-webcomponents/fonts/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff b/src/components/fonts/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff similarity index 100% rename from src/bower_components/emby-webcomponents/fonts/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff rename to src/components/fonts/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff diff --git a/src/bower_components/emby-webcomponents/fonts/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2 b/src/components/fonts/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2 similarity index 100% rename from src/bower_components/emby-webcomponents/fonts/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2 rename to src/components/fonts/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2 diff --git a/src/bower_components/emby-webcomponents/fonts/material-icons/style.css b/src/components/fonts/material-icons/style.css similarity index 100% rename from src/bower_components/emby-webcomponents/fonts/material-icons/style.css rename to src/components/fonts/material-icons/style.css diff --git a/src/bower_components/emby-webcomponents/formdialog.css b/src/components/formdialog.css similarity index 100% rename from src/bower_components/emby-webcomponents/formdialog.css rename to src/components/formdialog.css diff --git a/src/bower_components/emby-webcomponents/fullscreen/fullscreen-dc.js b/src/components/fullscreen/fullscreen-dc.js similarity index 100% rename from src/bower_components/emby-webcomponents/fullscreen/fullscreen-dc.js rename to src/components/fullscreen/fullscreen-dc.js diff --git a/src/bower_components/emby-webcomponents/fullscreen/fullscreenmanager.js b/src/components/fullscreen/fullscreenmanager.js similarity index 100% rename from src/bower_components/emby-webcomponents/fullscreen/fullscreenmanager.js rename to src/components/fullscreen/fullscreenmanager.js diff --git a/src/bower_components/emby-webcomponents/globalize.js b/src/components/globalize.js similarity index 100% rename from src/bower_components/emby-webcomponents/globalize.js rename to src/components/globalize.js diff --git a/src/bower_components/emby-webcomponents/guide/guide-settings.js b/src/components/guide/guide-settings.js similarity index 100% rename from src/bower_components/emby-webcomponents/guide/guide-settings.js rename to src/components/guide/guide-settings.js diff --git a/src/bower_components/emby-webcomponents/guide/guide-settings.template.html b/src/components/guide/guide-settings.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/guide/guide-settings.template.html rename to src/components/guide/guide-settings.template.html diff --git a/src/bower_components/emby-webcomponents/guide/guide.css b/src/components/guide/guide.css similarity index 100% rename from src/bower_components/emby-webcomponents/guide/guide.css rename to src/components/guide/guide.css diff --git a/src/bower_components/emby-webcomponents/guide/guide.js b/src/components/guide/guide.js similarity index 100% rename from src/bower_components/emby-webcomponents/guide/guide.js rename to src/components/guide/guide.js diff --git a/src/bower_components/emby-webcomponents/guide/programs.css b/src/components/guide/programs.css similarity index 100% rename from src/bower_components/emby-webcomponents/guide/programs.css rename to src/components/guide/programs.css diff --git a/src/bower_components/emby-webcomponents/guide/tvguide.template.html b/src/components/guide/tvguide.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/guide/tvguide.template.html rename to src/components/guide/tvguide.template.html diff --git a/src/bower_components/emby-webcomponents/headroom/headroom.css b/src/components/headroom/headroom.css similarity index 100% rename from src/bower_components/emby-webcomponents/headroom/headroom.css rename to src/components/headroom/headroom.css diff --git a/src/bower_components/emby-webcomponents/headroom/headroom.js b/src/components/headroom/headroom.js similarity index 100% rename from src/bower_components/emby-webcomponents/headroom/headroom.js rename to src/components/headroom/headroom.js diff --git a/src/bower_components/emby-webcomponents/homescreensettings/homescreensettings.js b/src/components/homescreensettings/homescreensettings.js similarity index 100% rename from src/bower_components/emby-webcomponents/homescreensettings/homescreensettings.js rename to src/components/homescreensettings/homescreensettings.js diff --git a/src/bower_components/emby-webcomponents/homescreensettings/homescreensettings.template.html b/src/components/homescreensettings/homescreensettings.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/homescreensettings/homescreensettings.template.html rename to src/components/homescreensettings/homescreensettings.template.html diff --git a/src/bower_components/emby-webcomponents/homescreensettings/homescreensettingsdialog.js b/src/components/homescreensettings/homescreensettingsdialog.js similarity index 100% rename from src/bower_components/emby-webcomponents/homescreensettings/homescreensettingsdialog.js rename to src/components/homescreensettings/homescreensettingsdialog.js diff --git a/src/bower_components/emby-webcomponents/homescreensettings/homescreensettingsdialog.template.html b/src/components/homescreensettings/homescreensettingsdialog.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/homescreensettings/homescreensettingsdialog.template.html rename to src/components/homescreensettings/homescreensettingsdialog.template.html diff --git a/src/bower_components/emby-webcomponents/homesections/homesections.css b/src/components/homesections/homesections.css similarity index 100% rename from src/bower_components/emby-webcomponents/homesections/homesections.css rename to src/components/homesections/homesections.css diff --git a/src/bower_components/emby-webcomponents/homesections/homesections.js b/src/components/homesections/homesections.js similarity index 100% rename from src/bower_components/emby-webcomponents/homesections/homesections.js rename to src/components/homesections/homesections.js diff --git a/src/bower_components/emby-webcomponents/htmlaudioplayer/plugin.js b/src/components/htmlaudioplayer/plugin.js similarity index 100% rename from src/bower_components/emby-webcomponents/htmlaudioplayer/plugin.js rename to src/components/htmlaudioplayer/plugin.js diff --git a/src/bower_components/emby-webcomponents/htmlvideoplayer/htmlmediahelper.js b/src/components/htmlvideoplayer/htmlmediahelper.js similarity index 100% rename from src/bower_components/emby-webcomponents/htmlvideoplayer/htmlmediahelper.js rename to src/components/htmlvideoplayer/htmlmediahelper.js diff --git a/src/bower_components/emby-webcomponents/htmlvideoplayer/plugin.js b/src/components/htmlvideoplayer/plugin.js similarity index 100% rename from src/bower_components/emby-webcomponents/htmlvideoplayer/plugin.js rename to src/components/htmlvideoplayer/plugin.js diff --git a/src/bower_components/emby-webcomponents/htmlvideoplayer/style.css b/src/components/htmlvideoplayer/style.css similarity index 100% rename from src/bower_components/emby-webcomponents/htmlvideoplayer/style.css rename to src/components/htmlvideoplayer/style.css diff --git a/src/bower_components/emby-webcomponents/imagedownloader/imagedownloader.js b/src/components/imagedownloader/imagedownloader.js similarity index 100% rename from src/bower_components/emby-webcomponents/imagedownloader/imagedownloader.js rename to src/components/imagedownloader/imagedownloader.js diff --git a/src/bower_components/emby-webcomponents/imagedownloader/imagedownloader.template.html b/src/components/imagedownloader/imagedownloader.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/imagedownloader/imagedownloader.template.html rename to src/components/imagedownloader/imagedownloader.template.html diff --git a/src/bower_components/emby-webcomponents/imageeditor/imageeditor.css b/src/components/imageeditor/imageeditor.css similarity index 100% rename from src/bower_components/emby-webcomponents/imageeditor/imageeditor.css rename to src/components/imageeditor/imageeditor.css diff --git a/src/bower_components/emby-webcomponents/imageeditor/imageeditor.js b/src/components/imageeditor/imageeditor.js similarity index 100% rename from src/bower_components/emby-webcomponents/imageeditor/imageeditor.js rename to src/components/imageeditor/imageeditor.js diff --git a/src/bower_components/emby-webcomponents/imageeditor/imageeditor.template.html b/src/components/imageeditor/imageeditor.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/imageeditor/imageeditor.template.html rename to src/components/imageeditor/imageeditor.template.html diff --git a/src/bower_components/emby-webcomponents/images/basicimagefetcher.js b/src/components/images/basicimagefetcher.js similarity index 100% rename from src/bower_components/emby-webcomponents/images/basicimagefetcher.js rename to src/components/images/basicimagefetcher.js diff --git a/src/bower_components/emby-webcomponents/images/imagehelper.js b/src/components/images/imagehelper.js similarity index 100% rename from src/bower_components/emby-webcomponents/images/imagehelper.js rename to src/components/images/imagehelper.js diff --git a/src/bower_components/emby-webcomponents/images/style.css b/src/components/images/style.css similarity index 100% rename from src/bower_components/emby-webcomponents/images/style.css rename to src/components/images/style.css diff --git a/src/bower_components/emby-webcomponents/imageuploader/imageuploader.js b/src/components/imageuploader/imageuploader.js similarity index 100% rename from src/bower_components/emby-webcomponents/imageuploader/imageuploader.js rename to src/components/imageuploader/imageuploader.js diff --git a/src/bower_components/emby-webcomponents/imageuploader/imageuploader.template.html b/src/components/imageuploader/imageuploader.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/imageuploader/imageuploader.template.html rename to src/components/imageuploader/imageuploader.template.html diff --git a/src/bower_components/emby-webcomponents/imageuploader/style.css b/src/components/imageuploader/style.css similarity index 100% rename from src/bower_components/emby-webcomponents/imageuploader/style.css rename to src/components/imageuploader/style.css diff --git a/src/bower_components/emby-webcomponents/indicators/indicators.css b/src/components/indicators/indicators.css similarity index 100% rename from src/bower_components/emby-webcomponents/indicators/indicators.css rename to src/components/indicators/indicators.css diff --git a/src/bower_components/emby-webcomponents/indicators/indicators.js b/src/components/indicators/indicators.js similarity index 100% rename from src/bower_components/emby-webcomponents/indicators/indicators.js rename to src/components/indicators/indicators.js diff --git a/src/bower_components/emby-webcomponents/input/api.js b/src/components/input/api.js similarity index 100% rename from src/bower_components/emby-webcomponents/input/api.js rename to src/components/input/api.js diff --git a/src/bower_components/emby-webcomponents/input/gamepadtokey.js b/src/components/input/gamepadtokey.js similarity index 100% rename from src/bower_components/emby-webcomponents/input/gamepadtokey.js rename to src/components/input/gamepadtokey.js diff --git a/src/bower_components/emby-webcomponents/input/mouse.js b/src/components/input/mouse.js similarity index 100% rename from src/bower_components/emby-webcomponents/input/mouse.js rename to src/components/input/mouse.js diff --git a/src/bower_components/emby-webcomponents/inputmanager.js b/src/components/inputmanager.js similarity index 100% rename from src/bower_components/emby-webcomponents/inputmanager.js rename to src/components/inputmanager.js diff --git a/src/bower_components/emby-webcomponents/itemcontextmenu.js b/src/components/itemcontextmenu.js similarity index 100% rename from src/bower_components/emby-webcomponents/itemcontextmenu.js rename to src/components/itemcontextmenu.js diff --git a/src/bower_components/emby-webcomponents/itemhelper.js b/src/components/itemhelper.js similarity index 100% rename from src/bower_components/emby-webcomponents/itemhelper.js rename to src/components/itemhelper.js diff --git a/src/bower_components/emby-webcomponents/itemidentifier/itemidentifier.js b/src/components/itemidentifier/itemidentifier.js similarity index 100% rename from src/bower_components/emby-webcomponents/itemidentifier/itemidentifier.js rename to src/components/itemidentifier/itemidentifier.js diff --git a/src/bower_components/emby-webcomponents/itemidentifier/itemidentifier.template.html b/src/components/itemidentifier/itemidentifier.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/itemidentifier/itemidentifier.template.html rename to src/components/itemidentifier/itemidentifier.template.html diff --git a/src/bower_components/emby-webcomponents/itemsrefresher.js b/src/components/itemsrefresher.js similarity index 100% rename from src/bower_components/emby-webcomponents/itemsrefresher.js rename to src/components/itemsrefresher.js diff --git a/src/bower_components/emby-webcomponents/layoutmanager.js b/src/components/layoutmanager.js similarity index 100% rename from src/bower_components/emby-webcomponents/layoutmanager.js rename to src/components/layoutmanager.js diff --git a/src/bower_components/emby-webcomponents/lazyloader/lazyedgehack.css b/src/components/lazyloader/lazyedgehack.css similarity index 100% rename from src/bower_components/emby-webcomponents/lazyloader/lazyedgehack.css rename to src/components/lazyloader/lazyedgehack.css diff --git a/src/bower_components/emby-webcomponents/lazyloader/lazyloader-intersectionobserver.js b/src/components/lazyloader/lazyloader-intersectionobserver.js similarity index 100% rename from src/bower_components/emby-webcomponents/lazyloader/lazyloader-intersectionobserver.js rename to src/components/lazyloader/lazyloader-intersectionobserver.js diff --git a/src/bower_components/emby-webcomponents/lazyloader/lazyloader-scroll.js b/src/components/lazyloader/lazyloader-scroll.js similarity index 100% rename from src/bower_components/emby-webcomponents/lazyloader/lazyloader-scroll.js rename to src/components/lazyloader/lazyloader-scroll.js diff --git a/src/bower_components/emby-webcomponents/listview/listview.css b/src/components/listview/listview.css similarity index 100% rename from src/bower_components/emby-webcomponents/listview/listview.css rename to src/components/listview/listview.css diff --git a/src/bower_components/emby-webcomponents/listview/listview.js b/src/components/listview/listview.js similarity index 100% rename from src/bower_components/emby-webcomponents/listview/listview.js rename to src/components/listview/listview.js diff --git a/src/bower_components/emby-webcomponents/loading/loader2.gif b/src/components/loading/loader2.gif similarity index 100% rename from src/bower_components/emby-webcomponents/loading/loader2.gif rename to src/components/loading/loader2.gif diff --git a/src/bower_components/emby-webcomponents/loading/loading-legacy.css b/src/components/loading/loading-legacy.css similarity index 100% rename from src/bower_components/emby-webcomponents/loading/loading-legacy.css rename to src/components/loading/loading-legacy.css diff --git a/src/bower_components/emby-webcomponents/loading/loading-legacy.js b/src/components/loading/loading-legacy.js similarity index 100% rename from src/bower_components/emby-webcomponents/loading/loading-legacy.js rename to src/components/loading/loading-legacy.js diff --git a/src/bower_components/emby-webcomponents/loading/loading-lite.css b/src/components/loading/loading-lite.css similarity index 100% rename from src/bower_components/emby-webcomponents/loading/loading-lite.css rename to src/components/loading/loading-lite.css diff --git a/src/bower_components/emby-webcomponents/loading/loading-lite.js b/src/components/loading/loading-lite.js similarity index 100% rename from src/bower_components/emby-webcomponents/loading/loading-lite.js rename to src/components/loading/loading-lite.js diff --git a/src/bower_components/emby-webcomponents/loadingdialog/loadingdialog.js b/src/components/loadingdialog/loadingdialog.js similarity index 100% rename from src/bower_components/emby-webcomponents/loadingdialog/loadingdialog.js rename to src/components/loadingdialog/loadingdialog.js diff --git a/src/bower_components/emby-webcomponents/maintabsmanager.js b/src/components/maintabsmanager.js similarity index 100% rename from src/bower_components/emby-webcomponents/maintabsmanager.js rename to src/components/maintabsmanager.js diff --git a/src/bower_components/emby-webcomponents/mediainfo/fresh.png b/src/components/mediainfo/fresh.png similarity index 100% rename from src/bower_components/emby-webcomponents/mediainfo/fresh.png rename to src/components/mediainfo/fresh.png diff --git a/src/bower_components/emby-webcomponents/mediainfo/mediainfo.css b/src/components/mediainfo/mediainfo.css similarity index 100% rename from src/bower_components/emby-webcomponents/mediainfo/mediainfo.css rename to src/components/mediainfo/mediainfo.css diff --git a/src/bower_components/emby-webcomponents/mediainfo/mediainfo.js b/src/components/mediainfo/mediainfo.js similarity index 100% rename from src/bower_components/emby-webcomponents/mediainfo/mediainfo.js rename to src/components/mediainfo/mediainfo.js diff --git a/src/bower_components/emby-webcomponents/mediainfo/rotten.png b/src/components/mediainfo/rotten.png similarity index 100% rename from src/bower_components/emby-webcomponents/mediainfo/rotten.png rename to src/components/mediainfo/rotten.png diff --git a/src/bower_components/emby-webcomponents/metadataeditor/metadataeditor.js b/src/components/metadataeditor/metadataeditor.js similarity index 100% rename from src/bower_components/emby-webcomponents/metadataeditor/metadataeditor.js rename to src/components/metadataeditor/metadataeditor.js diff --git a/src/bower_components/emby-webcomponents/metadataeditor/metadataeditor.template.html b/src/components/metadataeditor/metadataeditor.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/metadataeditor/metadataeditor.template.html rename to src/components/metadataeditor/metadataeditor.template.html diff --git a/src/bower_components/emby-webcomponents/metadataeditor/personeditor.js b/src/components/metadataeditor/personeditor.js similarity index 100% rename from src/bower_components/emby-webcomponents/metadataeditor/personeditor.js rename to src/components/metadataeditor/personeditor.js diff --git a/src/bower_components/emby-webcomponents/metadataeditor/personeditor.template.html b/src/components/metadataeditor/personeditor.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/metadataeditor/personeditor.template.html rename to src/components/metadataeditor/personeditor.template.html diff --git a/src/bower_components/emby-webcomponents/multidownload.js b/src/components/multidownload.js similarity index 100% rename from src/bower_components/emby-webcomponents/multidownload.js rename to src/components/multidownload.js diff --git a/src/bower_components/emby-webcomponents/multiselect/multiselect.css b/src/components/multiselect/multiselect.css similarity index 100% rename from src/bower_components/emby-webcomponents/multiselect/multiselect.css rename to src/components/multiselect/multiselect.css diff --git a/src/bower_components/emby-webcomponents/multiselect/multiselect.js b/src/components/multiselect/multiselect.js similarity index 100% rename from src/bower_components/emby-webcomponents/multiselect/multiselect.js rename to src/components/multiselect/multiselect.js diff --git a/src/bower_components/emby-webcomponents/native-promise-only/lib/npo.src.js b/src/components/native-promise-only/lib/npo.src.js similarity index 100% rename from src/bower_components/emby-webcomponents/native-promise-only/lib/npo.src.js rename to src/components/native-promise-only/lib/npo.src.js diff --git a/src/bower_components/emby-webcomponents/native-promise-only/test_adapter.js b/src/components/native-promise-only/test_adapter.js similarity index 100% rename from src/bower_components/emby-webcomponents/native-promise-only/test_adapter.js rename to src/components/native-promise-only/test_adapter.js diff --git a/src/bower_components/emby-webcomponents/notifications/badge.png b/src/components/notifications/badge.png similarity index 100% rename from src/bower_components/emby-webcomponents/notifications/badge.png rename to src/components/notifications/badge.png diff --git a/src/bower_components/emby-webcomponents/notifications/notificationicon.png b/src/components/notifications/notificationicon.png similarity index 100% rename from src/bower_components/emby-webcomponents/notifications/notificationicon.png rename to src/components/notifications/notificationicon.png diff --git a/src/bower_components/emby-webcomponents/notifications/notifications.js b/src/components/notifications/notifications.js similarity index 100% rename from src/bower_components/emby-webcomponents/notifications/notifications.js rename to src/components/notifications/notifications.js diff --git a/src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.css b/src/components/nowplayingbar/nowplayingbar.css similarity index 100% rename from src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.css rename to src/components/nowplayingbar/nowplayingbar.css diff --git a/src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.js b/src/components/nowplayingbar/nowplayingbar.js similarity index 100% rename from src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.js rename to src/components/nowplayingbar/nowplayingbar.js diff --git a/src/bower_components/emby-webcomponents/packagemanager.js b/src/components/packagemanager.js similarity index 100% rename from src/bower_components/emby-webcomponents/packagemanager.js rename to src/components/packagemanager.js diff --git a/src/bower_components/emby-webcomponents/pagejs/page.js b/src/components/pagejs/page.js similarity index 100% rename from src/bower_components/emby-webcomponents/pagejs/page.js rename to src/components/pagejs/page.js diff --git a/src/bower_components/emby-webcomponents/photoplayer/plugin.js b/src/components/photoplayer/plugin.js similarity index 100% rename from src/bower_components/emby-webcomponents/photoplayer/plugin.js rename to src/components/photoplayer/plugin.js diff --git a/src/bower_components/emby-webcomponents/playback/autoplaydetect.js b/src/components/playback/autoplaydetect.js similarity index 100% rename from src/bower_components/emby-webcomponents/playback/autoplaydetect.js rename to src/components/playback/autoplaydetect.js diff --git a/src/bower_components/emby-webcomponents/playback/brightnessosd.js b/src/components/playback/brightnessosd.js similarity index 100% rename from src/bower_components/emby-webcomponents/playback/brightnessosd.js rename to src/components/playback/brightnessosd.js diff --git a/src/bower_components/emby-webcomponents/playback/experimentalwarnings.js b/src/components/playback/experimentalwarnings.js similarity index 100% rename from src/bower_components/emby-webcomponents/playback/experimentalwarnings.js rename to src/components/playback/experimentalwarnings.js diff --git a/src/bower_components/emby-webcomponents/playback/iconosd.css b/src/components/playback/iconosd.css similarity index 100% rename from src/bower_components/emby-webcomponents/playback/iconosd.css rename to src/components/playback/iconosd.css diff --git a/src/bower_components/emby-webcomponents/playback/mediasession.js b/src/components/playback/mediasession.js similarity index 100% rename from src/bower_components/emby-webcomponents/playback/mediasession.js rename to src/components/playback/mediasession.js diff --git a/src/bower_components/emby-webcomponents/playback/nowplayinghelper.js b/src/components/playback/nowplayinghelper.js similarity index 100% rename from src/bower_components/emby-webcomponents/playback/nowplayinghelper.js rename to src/components/playback/nowplayinghelper.js diff --git a/src/bower_components/emby-webcomponents/playback/playaccessvalidation.js b/src/components/playback/playaccessvalidation.js similarity index 100% rename from src/bower_components/emby-webcomponents/playback/playaccessvalidation.js rename to src/components/playback/playaccessvalidation.js diff --git a/src/bower_components/emby-webcomponents/playback/playbackmanager.js b/src/components/playback/playbackmanager.js similarity index 100% rename from src/bower_components/emby-webcomponents/playback/playbackmanager.js rename to src/components/playback/playbackmanager.js diff --git a/src/bower_components/emby-webcomponents/playback/playbackorientation.js b/src/components/playback/playbackorientation.js similarity index 100% rename from src/bower_components/emby-webcomponents/playback/playbackorientation.js rename to src/components/playback/playbackorientation.js diff --git a/src/bower_components/emby-webcomponents/playback/playbackvalidation.js b/src/components/playback/playbackvalidation.js similarity index 100% rename from src/bower_components/emby-webcomponents/playback/playbackvalidation.js rename to src/components/playback/playbackvalidation.js diff --git a/src/bower_components/emby-webcomponents/playback/playerselection.js b/src/components/playback/playerselection.js similarity index 100% rename from src/bower_components/emby-webcomponents/playback/playerselection.js rename to src/components/playback/playerselection.js diff --git a/src/bower_components/emby-webcomponents/playback/playersettingsmenu.js b/src/components/playback/playersettingsmenu.js similarity index 100% rename from src/bower_components/emby-webcomponents/playback/playersettingsmenu.js rename to src/components/playback/playersettingsmenu.js diff --git a/src/bower_components/emby-webcomponents/playback/playmethodhelper.js b/src/components/playback/playmethodhelper.js similarity index 100% rename from src/bower_components/emby-webcomponents/playback/playmethodhelper.js rename to src/components/playback/playmethodhelper.js diff --git a/src/bower_components/emby-webcomponents/playback/playqueuemanager.js b/src/components/playback/playqueuemanager.js similarity index 100% rename from src/bower_components/emby-webcomponents/playback/playqueuemanager.js rename to src/components/playback/playqueuemanager.js diff --git a/src/bower_components/emby-webcomponents/playback/remotecontrolautoplay.js b/src/components/playback/remotecontrolautoplay.js similarity index 100% rename from src/bower_components/emby-webcomponents/playback/remotecontrolautoplay.js rename to src/components/playback/remotecontrolautoplay.js diff --git a/src/bower_components/emby-webcomponents/playback/volumeosd.js b/src/components/playback/volumeosd.js similarity index 100% rename from src/bower_components/emby-webcomponents/playback/volumeosd.js rename to src/components/playback/volumeosd.js diff --git a/src/bower_components/emby-webcomponents/playbacksettings/playbacksettings.js b/src/components/playbacksettings/playbacksettings.js similarity index 100% rename from src/bower_components/emby-webcomponents/playbacksettings/playbacksettings.js rename to src/components/playbacksettings/playbacksettings.js diff --git a/src/bower_components/emby-webcomponents/playbacksettings/playbacksettings.template.html b/src/components/playbacksettings/playbacksettings.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/playbacksettings/playbacksettings.template.html rename to src/components/playbacksettings/playbacksettings.template.html diff --git a/src/bower_components/emby-webcomponents/playerstats/playerstats.css b/src/components/playerstats/playerstats.css similarity index 100% rename from src/bower_components/emby-webcomponents/playerstats/playerstats.css rename to src/components/playerstats/playerstats.css diff --git a/src/bower_components/emby-webcomponents/playerstats/playerstats.js b/src/components/playerstats/playerstats.js similarity index 100% rename from src/bower_components/emby-webcomponents/playerstats/playerstats.js rename to src/components/playerstats/playerstats.js diff --git a/src/bower_components/emby-webcomponents/playlisteditor/playlisteditor.js b/src/components/playlisteditor/playlisteditor.js similarity index 100% rename from src/bower_components/emby-webcomponents/playlisteditor/playlisteditor.js rename to src/components/playlisteditor/playlisteditor.js diff --git a/src/bower_components/emby-webcomponents/playmenu.js b/src/components/playmenu.js similarity index 100% rename from src/bower_components/emby-webcomponents/playmenu.js rename to src/components/playmenu.js diff --git a/src/bower_components/emby-webcomponents/pluginmanager.js b/src/components/pluginmanager.js similarity index 100% rename from src/bower_components/emby-webcomponents/pluginmanager.js rename to src/components/pluginmanager.js diff --git a/src/bower_components/emby-webcomponents/polyfills/array.js b/src/components/polyfills/array.js similarity index 100% rename from src/bower_components/emby-webcomponents/polyfills/array.js rename to src/components/polyfills/array.js diff --git a/src/bower_components/emby-webcomponents/polyfills/bind.js b/src/components/polyfills/bind.js similarity index 100% rename from src/bower_components/emby-webcomponents/polyfills/bind.js rename to src/components/polyfills/bind.js diff --git a/src/bower_components/emby-webcomponents/polyfills/objectassign.js b/src/components/polyfills/objectassign.js similarity index 100% rename from src/bower_components/emby-webcomponents/polyfills/objectassign.js rename to src/components/polyfills/objectassign.js diff --git a/src/bower_components/emby-webcomponents/polyfills/raf.js b/src/components/polyfills/raf.js similarity index 100% rename from src/bower_components/emby-webcomponents/polyfills/raf.js rename to src/components/polyfills/raf.js diff --git a/src/bower_components/emby-webcomponents/prompt/nativeprompt.js b/src/components/prompt/nativeprompt.js similarity index 100% rename from src/bower_components/emby-webcomponents/prompt/nativeprompt.js rename to src/components/prompt/nativeprompt.js diff --git a/src/bower_components/emby-webcomponents/prompt/prompt.js b/src/components/prompt/prompt.js similarity index 100% rename from src/bower_components/emby-webcomponents/prompt/prompt.js rename to src/components/prompt/prompt.js diff --git a/src/bower_components/emby-webcomponents/prompt/prompt.template.html b/src/components/prompt/prompt.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/prompt/prompt.template.html rename to src/components/prompt/prompt.template.html diff --git a/src/bower_components/emby-webcomponents/qualityoptions.js b/src/components/qualityoptions.js similarity index 100% rename from src/bower_components/emby-webcomponents/qualityoptions.js rename to src/components/qualityoptions.js diff --git a/src/bower_components/emby-webcomponents/recordingcreator/empty.png b/src/components/recordingcreator/empty.png similarity index 100% rename from src/bower_components/emby-webcomponents/recordingcreator/empty.png rename to src/components/recordingcreator/empty.png diff --git a/src/bower_components/emby-webcomponents/recordingcreator/recordingbutton.js b/src/components/recordingcreator/recordingbutton.js similarity index 100% rename from src/bower_components/emby-webcomponents/recordingcreator/recordingbutton.js rename to src/components/recordingcreator/recordingbutton.js diff --git a/src/bower_components/emby-webcomponents/recordingcreator/recordingcreator.css b/src/components/recordingcreator/recordingcreator.css similarity index 100% rename from src/bower_components/emby-webcomponents/recordingcreator/recordingcreator.css rename to src/components/recordingcreator/recordingcreator.css diff --git a/src/bower_components/emby-webcomponents/recordingcreator/recordingcreator.js b/src/components/recordingcreator/recordingcreator.js similarity index 100% rename from src/bower_components/emby-webcomponents/recordingcreator/recordingcreator.js rename to src/components/recordingcreator/recordingcreator.js diff --git a/src/bower_components/emby-webcomponents/recordingcreator/recordingcreator.template.html b/src/components/recordingcreator/recordingcreator.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/recordingcreator/recordingcreator.template.html rename to src/components/recordingcreator/recordingcreator.template.html diff --git a/src/bower_components/emby-webcomponents/recordingcreator/recordingeditor.js b/src/components/recordingcreator/recordingeditor.js similarity index 100% rename from src/bower_components/emby-webcomponents/recordingcreator/recordingeditor.js rename to src/components/recordingcreator/recordingeditor.js diff --git a/src/bower_components/emby-webcomponents/recordingcreator/recordingeditor.template.html b/src/components/recordingcreator/recordingeditor.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/recordingcreator/recordingeditor.template.html rename to src/components/recordingcreator/recordingeditor.template.html diff --git a/src/bower_components/emby-webcomponents/recordingcreator/recordingfields.css b/src/components/recordingcreator/recordingfields.css similarity index 100% rename from src/bower_components/emby-webcomponents/recordingcreator/recordingfields.css rename to src/components/recordingcreator/recordingfields.css diff --git a/src/bower_components/emby-webcomponents/recordingcreator/recordingfields.js b/src/components/recordingcreator/recordingfields.js similarity index 100% rename from src/bower_components/emby-webcomponents/recordingcreator/recordingfields.js rename to src/components/recordingcreator/recordingfields.js diff --git a/src/bower_components/emby-webcomponents/recordingcreator/recordingfields.template.html b/src/components/recordingcreator/recordingfields.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/recordingcreator/recordingfields.template.html rename to src/components/recordingcreator/recordingfields.template.html diff --git a/src/bower_components/emby-webcomponents/recordingcreator/recordinghelper.js b/src/components/recordingcreator/recordinghelper.js similarity index 100% rename from src/bower_components/emby-webcomponents/recordingcreator/recordinghelper.js rename to src/components/recordingcreator/recordinghelper.js diff --git a/src/bower_components/emby-webcomponents/recordingcreator/seriesrecordingeditor.js b/src/components/recordingcreator/seriesrecordingeditor.js similarity index 100% rename from src/bower_components/emby-webcomponents/recordingcreator/seriesrecordingeditor.js rename to src/components/recordingcreator/seriesrecordingeditor.js diff --git a/src/bower_components/emby-webcomponents/recordingcreator/seriesrecordingeditor.template.html b/src/components/recordingcreator/seriesrecordingeditor.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/recordingcreator/seriesrecordingeditor.template.html rename to src/components/recordingcreator/seriesrecordingeditor.template.html diff --git a/src/bower_components/emby-webcomponents/refreshdialog/refreshdialog.js b/src/components/refreshdialog/refreshdialog.js similarity index 100% rename from src/bower_components/emby-webcomponents/refreshdialog/refreshdialog.js rename to src/components/refreshdialog/refreshdialog.js diff --git a/src/bower_components/emby-webcomponents/registrationservices/registrationservices.js b/src/components/registrationservices/registrationservices.js similarity index 100% rename from src/bower_components/emby-webcomponents/registrationservices/registrationservices.js rename to src/components/registrationservices/registrationservices.js diff --git a/src/bower_components/emby-webcomponents/require/requirecss.js b/src/components/require/requirecss.js similarity index 96% rename from src/bower_components/emby-webcomponents/require/requirecss.js rename to src/components/require/requirecss.js index f65ed1fd04..78e5af2a08 100644 --- a/src/bower_components/emby-webcomponents/require/requirecss.js +++ b/src/components/require/requirecss.js @@ -29,7 +29,7 @@ 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 - var srch = '/emby-webcomponents/require/requirecss'; + var srch = 'components/require/requirecss'; var index = cssId.indexOf(srch); if (index !== -1) { diff --git a/src/bower_components/emby-webcomponents/require/requiretext.js b/src/components/require/requiretext.js similarity index 100% rename from src/bower_components/emby-webcomponents/require/requiretext.js rename to src/components/require/requiretext.js diff --git a/src/bower_components/emby-webcomponents/resize-observer-polyfill/ResizeObserver.js b/src/components/resize-observer-polyfill/ResizeObserver.js similarity index 100% rename from src/bower_components/emby-webcomponents/resize-observer-polyfill/ResizeObserver.js rename to src/components/resize-observer-polyfill/ResizeObserver.js diff --git a/src/bower_components/emby-webcomponents/router.js b/src/components/router.js similarity index 100% rename from src/bower_components/emby-webcomponents/router.js rename to src/components/router.js diff --git a/src/bower_components/emby-webcomponents/sanitizefilename.js b/src/components/sanitizefilename.js similarity index 100% rename from src/bower_components/emby-webcomponents/sanitizefilename.js rename to src/components/sanitizefilename.js diff --git a/src/bower_components/emby-webcomponents/scroller/smoothscroller.js b/src/components/scroller/smoothscroller.js similarity index 100% rename from src/bower_components/emby-webcomponents/scroller/smoothscroller.js rename to src/components/scroller/smoothscroller.js diff --git a/src/bower_components/emby-webcomponents/scrollhelper.js b/src/components/scrollhelper.js similarity index 100% rename from src/bower_components/emby-webcomponents/scrollhelper.js rename to src/components/scrollhelper.js diff --git a/src/bower_components/emby-webcomponents/scrollstyles.css b/src/components/scrollstyles.css similarity index 100% rename from src/bower_components/emby-webcomponents/scrollstyles.css rename to src/components/scrollstyles.css diff --git a/src/bower_components/emby-webcomponents/search/searchfields.css b/src/components/search/searchfields.css similarity index 100% rename from src/bower_components/emby-webcomponents/search/searchfields.css rename to src/components/search/searchfields.css diff --git a/src/bower_components/emby-webcomponents/search/searchfields.js b/src/components/search/searchfields.js similarity index 100% rename from src/bower_components/emby-webcomponents/search/searchfields.js rename to src/components/search/searchfields.js diff --git a/src/bower_components/emby-webcomponents/search/searchfields.template.html b/src/components/search/searchfields.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/search/searchfields.template.html rename to src/components/search/searchfields.template.html diff --git a/src/bower_components/emby-webcomponents/search/searchresults.js b/src/components/search/searchresults.js similarity index 100% rename from src/bower_components/emby-webcomponents/search/searchresults.js rename to src/components/search/searchresults.js diff --git a/src/bower_components/emby-webcomponents/search/searchresults.template.html b/src/components/search/searchresults.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/search/searchresults.template.html rename to src/components/search/searchresults.template.html diff --git a/src/bower_components/emby-webcomponents/serverrestartdialog/serverrestartdialog.js b/src/components/serverrestartdialog/serverrestartdialog.js similarity index 100% rename from src/bower_components/emby-webcomponents/serverrestartdialog/serverrestartdialog.js rename to src/components/serverrestartdialog/serverrestartdialog.js diff --git a/src/bower_components/emby-webcomponents/serviceworker/notifications.js b/src/components/serviceworker/notifications.js similarity index 100% rename from src/bower_components/emby-webcomponents/serviceworker/notifications.js rename to src/components/serviceworker/notifications.js diff --git a/src/bower_components/emby-webcomponents/serviceworker/sync.js b/src/components/serviceworker/sync.js similarity index 100% rename from src/bower_components/emby-webcomponents/serviceworker/sync.js rename to src/components/serviceworker/sync.js diff --git a/src/bower_components/emby-webcomponents/sessionplayer.js b/src/components/sessionplayer.js similarity index 100% rename from src/bower_components/emby-webcomponents/sessionplayer.js rename to src/components/sessionplayer.js diff --git a/src/bower_components/emby-webcomponents/shell.js b/src/components/shell.js similarity index 100% rename from src/bower_components/emby-webcomponents/shell.js rename to src/components/shell.js diff --git a/src/bower_components/emby-webcomponents/shortcuts.js b/src/components/shortcuts.js similarity index 100% rename from src/bower_components/emby-webcomponents/shortcuts.js rename to src/components/shortcuts.js diff --git a/src/bower_components/emby-webcomponents/skinmanager.js b/src/components/skinmanager.js similarity index 99% rename from src/bower_components/emby-webcomponents/skinmanager.js rename to src/components/skinmanager.js index 48820512cf..556250137a 100644 --- a/src/bower_components/emby-webcomponents/skinmanager.js +++ b/src/components/skinmanager.js @@ -219,7 +219,7 @@ define(['apphost', 'userSettings', 'browser', 'events', 'pluginManager', 'backdr selectedTheme = defaultTheme; } - var embyWebComponentsBowerPath = 'bower_components/emby-webcomponents'; + var embyWebComponentsBowerPath = 'components'; return { stylesheetPath: require.toUrl(embyWebComponentsBowerPath + '/themes/' + selectedTheme.id + '/theme.css'), diff --git a/src/bower_components/emby-webcomponents/slideshow/slideshow.js b/src/components/slideshow/slideshow.js similarity index 100% rename from src/bower_components/emby-webcomponents/slideshow/slideshow.js rename to src/components/slideshow/slideshow.js diff --git a/src/bower_components/emby-webcomponents/slideshow/style.css b/src/components/slideshow/style.css similarity index 100% rename from src/bower_components/emby-webcomponents/slideshow/style.css rename to src/components/slideshow/style.css diff --git a/src/bower_components/emby-webcomponents/sortmenu/sortmenu.js b/src/components/sortmenu/sortmenu.js similarity index 100% rename from src/bower_components/emby-webcomponents/sortmenu/sortmenu.js rename to src/components/sortmenu/sortmenu.js diff --git a/src/bower_components/emby-webcomponents/sortmenu/sortmenu.template.html b/src/components/sortmenu/sortmenu.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/sortmenu/sortmenu.template.html rename to src/components/sortmenu/sortmenu.template.html diff --git a/src/bower_components/emby-webcomponents/staticbackdrops.js b/src/components/staticbackdrops.js similarity index 100% rename from src/bower_components/emby-webcomponents/staticbackdrops.js rename to src/components/staticbackdrops.js diff --git a/src/bower_components/emby-webcomponents/subtitleeditor/subtitleeditor.css b/src/components/subtitleeditor/subtitleeditor.css similarity index 100% rename from src/bower_components/emby-webcomponents/subtitleeditor/subtitleeditor.css rename to src/components/subtitleeditor/subtitleeditor.css diff --git a/src/bower_components/emby-webcomponents/subtitleeditor/subtitleeditor.js b/src/components/subtitleeditor/subtitleeditor.js similarity index 100% rename from src/bower_components/emby-webcomponents/subtitleeditor/subtitleeditor.js rename to src/components/subtitleeditor/subtitleeditor.js diff --git a/src/bower_components/emby-webcomponents/subtitleeditor/subtitleeditor.template.html b/src/components/subtitleeditor/subtitleeditor.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/subtitleeditor/subtitleeditor.template.html rename to src/components/subtitleeditor/subtitleeditor.template.html diff --git a/src/bower_components/emby-webcomponents/subtitlesettings/subtitleappearancehelper.js b/src/components/subtitlesettings/subtitleappearancehelper.js similarity index 100% rename from src/bower_components/emby-webcomponents/subtitlesettings/subtitleappearancehelper.js rename to src/components/subtitlesettings/subtitleappearancehelper.js diff --git a/src/bower_components/emby-webcomponents/subtitlesettings/subtitlesettings.js b/src/components/subtitlesettings/subtitlesettings.js similarity index 100% rename from src/bower_components/emby-webcomponents/subtitlesettings/subtitlesettings.js rename to src/components/subtitlesettings/subtitlesettings.js diff --git a/src/bower_components/emby-webcomponents/subtitlesettings/subtitlesettings.template.html b/src/components/subtitlesettings/subtitlesettings.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/subtitlesettings/subtitlesettings.template.html rename to src/components/subtitlesettings/subtitlesettings.template.html diff --git a/src/bower_components/emby-webcomponents/sync/emby-downloadbutton.js b/src/components/sync/emby-downloadbutton.js similarity index 100% rename from src/bower_components/emby-webcomponents/sync/emby-downloadbutton.js rename to src/components/sync/emby-downloadbutton.js diff --git a/src/bower_components/emby-webcomponents/sync/sync.js b/src/components/sync/sync.js similarity index 100% rename from src/bower_components/emby-webcomponents/sync/sync.js rename to src/components/sync/sync.js diff --git a/src/bower_components/emby-webcomponents/tabbedview/itemstab.js b/src/components/tabbedview/itemstab.js similarity index 100% rename from src/bower_components/emby-webcomponents/tabbedview/itemstab.js rename to src/components/tabbedview/itemstab.js diff --git a/src/bower_components/emby-webcomponents/tabbedview/tabbedview.js b/src/components/tabbedview/tabbedview.js similarity index 100% rename from src/bower_components/emby-webcomponents/tabbedview/tabbedview.js rename to src/components/tabbedview/tabbedview.js diff --git a/src/bower_components/emby-webcomponents/thememediaplayer.js b/src/components/thememediaplayer.js similarity index 100% rename from src/bower_components/emby-webcomponents/thememediaplayer.js rename to src/components/thememediaplayer.js diff --git a/src/bower_components/emby-webcomponents/themes/appletv/theme.css b/src/components/themes/appletv/theme.css similarity index 100% rename from src/bower_components/emby-webcomponents/themes/appletv/theme.css rename to src/components/themes/appletv/theme.css diff --git a/src/bower_components/emby-webcomponents/themes/blueradiance/bg.jpg b/src/components/themes/blueradiance/bg.jpg similarity index 100% rename from src/bower_components/emby-webcomponents/themes/blueradiance/bg.jpg rename to src/components/themes/blueradiance/bg.jpg diff --git a/src/bower_components/emby-webcomponents/themes/blueradiance/theme.css b/src/components/themes/blueradiance/theme.css similarity index 100% rename from src/bower_components/emby-webcomponents/themes/blueradiance/theme.css rename to src/components/themes/blueradiance/theme.css diff --git a/src/bower_components/emby-webcomponents/themes/dark-classic/theme.css b/src/components/themes/dark-classic/theme.css similarity index 100% rename from src/bower_components/emby-webcomponents/themes/dark-classic/theme.css rename to src/components/themes/dark-classic/theme.css diff --git a/src/bower_components/emby-webcomponents/themes/dark-green/theme.css b/src/components/themes/dark-green/theme.css similarity index 100% rename from src/bower_components/emby-webcomponents/themes/dark-green/theme.css rename to src/components/themes/dark-green/theme.css diff --git a/src/bower_components/emby-webcomponents/themes/dark-red/theme.css b/src/components/themes/dark-red/theme.css similarity index 100% rename from src/bower_components/emby-webcomponents/themes/dark-red/theme.css rename to src/components/themes/dark-red/theme.css diff --git a/src/bower_components/emby-webcomponents/themes/dark/theme.css b/src/components/themes/dark/theme.css similarity index 100% rename from src/bower_components/emby-webcomponents/themes/dark/theme.css rename to src/components/themes/dark/theme.css diff --git a/src/bower_components/emby-webcomponents/themes/light-blue/theme.css b/src/components/themes/light-blue/theme.css similarity index 100% rename from src/bower_components/emby-webcomponents/themes/light-blue/theme.css rename to src/components/themes/light-blue/theme.css diff --git a/src/bower_components/emby-webcomponents/themes/light-classic/theme.css b/src/components/themes/light-classic/theme.css similarity index 100% rename from src/bower_components/emby-webcomponents/themes/light-classic/theme.css rename to src/components/themes/light-classic/theme.css diff --git a/src/bower_components/emby-webcomponents/themes/light-green/theme.css b/src/components/themes/light-green/theme.css similarity index 100% rename from src/bower_components/emby-webcomponents/themes/light-green/theme.css rename to src/components/themes/light-green/theme.css diff --git a/src/bower_components/emby-webcomponents/themes/light-pink/theme.css b/src/components/themes/light-pink/theme.css similarity index 100% rename from src/bower_components/emby-webcomponents/themes/light-pink/theme.css rename to src/components/themes/light-pink/theme.css diff --git a/src/bower_components/emby-webcomponents/themes/light-purple/theme.css b/src/components/themes/light-purple/theme.css similarity index 100% rename from src/bower_components/emby-webcomponents/themes/light-purple/theme.css rename to src/components/themes/light-purple/theme.css diff --git a/src/bower_components/emby-webcomponents/themes/light-red/theme.css b/src/components/themes/light-red/theme.css similarity index 100% rename from src/bower_components/emby-webcomponents/themes/light-red/theme.css rename to src/components/themes/light-red/theme.css diff --git a/src/bower_components/emby-webcomponents/themes/light/theme.css b/src/components/themes/light/theme.css similarity index 100% rename from src/bower_components/emby-webcomponents/themes/light/theme.css rename to src/components/themes/light/theme.css diff --git a/src/bower_components/emby-webcomponents/themes/logodark.png b/src/components/themes/logodark.png similarity index 100% rename from src/bower_components/emby-webcomponents/themes/logodark.png rename to src/components/themes/logodark.png diff --git a/src/bower_components/emby-webcomponents/themes/logowhite.png b/src/components/themes/logowhite.png similarity index 100% rename from src/bower_components/emby-webcomponents/themes/logowhite.png rename to src/components/themes/logowhite.png diff --git a/src/bower_components/emby-webcomponents/themes/wmc/theme.css b/src/components/themes/wmc/theme.css similarity index 100% rename from src/bower_components/emby-webcomponents/themes/wmc/theme.css rename to src/components/themes/wmc/theme.css diff --git a/src/bower_components/emby-webcomponents/toast/toast.css b/src/components/toast/toast.css similarity index 100% rename from src/bower_components/emby-webcomponents/toast/toast.css rename to src/components/toast/toast.css diff --git a/src/bower_components/emby-webcomponents/toast/toast.js b/src/components/toast/toast.js similarity index 100% rename from src/bower_components/emby-webcomponents/toast/toast.js rename to src/components/toast/toast.js diff --git a/src/bower_components/emby-webcomponents/touchhelper.js b/src/components/touchhelper.js similarity index 100% rename from src/bower_components/emby-webcomponents/touchhelper.js rename to src/components/touchhelper.js diff --git a/src/bower_components/emby-webcomponents/upnextdialog/upnextdialog.css b/src/components/upnextdialog/upnextdialog.css similarity index 100% rename from src/bower_components/emby-webcomponents/upnextdialog/upnextdialog.css rename to src/components/upnextdialog/upnextdialog.css diff --git a/src/bower_components/emby-webcomponents/upnextdialog/upnextdialog.js b/src/components/upnextdialog/upnextdialog.js similarity index 100% rename from src/bower_components/emby-webcomponents/upnextdialog/upnextdialog.js rename to src/components/upnextdialog/upnextdialog.js diff --git a/src/bower_components/emby-webcomponents/userdatabuttons/emby-playstatebutton.js b/src/components/userdatabuttons/emby-playstatebutton.js similarity index 100% rename from src/bower_components/emby-webcomponents/userdatabuttons/emby-playstatebutton.js rename to src/components/userdatabuttons/emby-playstatebutton.js diff --git a/src/bower_components/emby-webcomponents/userdatabuttons/emby-ratingbutton.js b/src/components/userdatabuttons/emby-ratingbutton.js similarity index 100% rename from src/bower_components/emby-webcomponents/userdatabuttons/emby-ratingbutton.js rename to src/components/userdatabuttons/emby-ratingbutton.js diff --git a/src/bower_components/emby-webcomponents/userdatabuttons/userdatabuttons.css b/src/components/userdatabuttons/userdatabuttons.css similarity index 100% rename from src/bower_components/emby-webcomponents/userdatabuttons/userdatabuttons.css rename to src/components/userdatabuttons/userdatabuttons.css diff --git a/src/bower_components/emby-webcomponents/userdatabuttons/userdatabuttons.js b/src/components/userdatabuttons/userdatabuttons.js similarity index 100% rename from src/bower_components/emby-webcomponents/userdatabuttons/userdatabuttons.js rename to src/components/userdatabuttons/userdatabuttons.js diff --git a/src/bower_components/emby-webcomponents/usersettings/usersettings.js b/src/components/usersettings/usersettings.js similarity index 100% rename from src/bower_components/emby-webcomponents/usersettings/usersettings.js rename to src/components/usersettings/usersettings.js diff --git a/src/bower_components/emby-webcomponents/usersettings/usersettingsbuilder.js b/src/components/usersettings/usersettingsbuilder.js similarity index 100% rename from src/bower_components/emby-webcomponents/usersettings/usersettingsbuilder.js rename to src/components/usersettings/usersettingsbuilder.js diff --git a/src/components/viewcontainer-lite.js b/src/components/viewcontainer-lite.js index d1729f1fab..fbcc2754e0 100644 --- a/src/components/viewcontainer-lite.js +++ b/src/components/viewcontainer-lite.js @@ -1,4 +1,4 @@ -define(["browser", "dom", "layoutManager", "css!bower_components/emby-webcomponents/viewmanager/viewcontainer-lite"], function(browser, dom, layoutManager) { +define(["browser", "dom", "layoutManager", "css!components/viewmanager/viewcontainer-lite"], function(browser, dom, layoutManager) { "use strict"; function setControllerClass(view, options) { diff --git a/src/bower_components/emby-webcomponents/viewmanager/viewcontainer-lite.css b/src/components/viewmanager/viewcontainer-lite.css similarity index 100% rename from src/bower_components/emby-webcomponents/viewmanager/viewcontainer-lite.css rename to src/components/viewmanager/viewcontainer-lite.css diff --git a/src/bower_components/emby-webcomponents/viewmanager/viewcontainer-lite.js b/src/components/viewmanager/viewcontainer-lite.js similarity index 100% rename from src/bower_components/emby-webcomponents/viewmanager/viewcontainer-lite.js rename to src/components/viewmanager/viewcontainer-lite.js diff --git a/src/bower_components/emby-webcomponents/viewmanager/viewmanager.js b/src/components/viewmanager/viewmanager.js similarity index 100% rename from src/bower_components/emby-webcomponents/viewmanager/viewmanager.js rename to src/components/viewmanager/viewmanager.js diff --git a/src/bower_components/emby-webcomponents/viewsettings/viewsettings.js b/src/components/viewsettings/viewsettings.js similarity index 100% rename from src/bower_components/emby-webcomponents/viewsettings/viewsettings.js rename to src/components/viewsettings/viewsettings.js diff --git a/src/bower_components/emby-webcomponents/viewsettings/viewsettings.template.html b/src/components/viewsettings/viewsettings.template.html similarity index 100% rename from src/bower_components/emby-webcomponents/viewsettings/viewsettings.template.html rename to src/components/viewsettings/viewsettings.template.html diff --git a/src/bower_components/emby-webcomponents/visibleinviewport.js b/src/components/visibleinviewport.js similarity index 100% rename from src/bower_components/emby-webcomponents/visibleinviewport.js rename to src/components/visibleinviewport.js diff --git a/src/bower_components/emby-webcomponents/youtubeplayer/plugin.js b/src/components/youtubeplayer/plugin.js similarity index 100% rename from src/bower_components/emby-webcomponents/youtubeplayer/plugin.js rename to src/components/youtubeplayer/plugin.js diff --git a/src/bower_components/emby-webcomponents/youtubeplayer/style.css b/src/components/youtubeplayer/style.css similarity index 100% rename from src/bower_components/emby-webcomponents/youtubeplayer/style.css rename to src/components/youtubeplayer/style.css diff --git a/src/scripts/site.js b/src/scripts/site.js index d30d27f9ea..984c01800e 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -431,14 +431,14 @@ var AppInfo = {}; return self.ResizeObserver; }); } else { - define("ResizeObserver", ["bower_components/emby-webcomponents/resize-observer-polyfill/ResizeObserver"], returnFirstDependency); + define("ResizeObserver", ["components/resize-observer-polyfill/ResizeObserver"], returnFirstDependency); } } function initRequireWithBrowser(browser) { var bowerPath = getBowerPath(); var apiClientBowerPath = bowerPath + "/emby-apiclient"; - var embyWebComponentsBowerPath = bowerPath + "/emby-webcomponents"; + var embyWebComponentsBowerPath = "components"; if ("android" === self.appMode) { define("filesystem", ["cordova/filesystem"], returnFirstDependency); @@ -1165,7 +1165,7 @@ var AppInfo = {}; function loadPlugins(externalPlugins, appHost, browser, shell) { console.log("Loading installed plugins"); - var list = ["bower_components/emby-webcomponents/playback/playbackvalidation", "bower_components/emby-webcomponents/playback/playaccessvalidation", "bower_components/emby-webcomponents/playback/experimentalwarnings", "bower_components/emby-webcomponents/htmlaudioplayer/plugin", "bower_components/emby-webcomponents/htmlvideoplayer/plugin", "bower_components/emby-webcomponents/photoplayer/plugin", "bower_components/emby-webcomponents/youtubeplayer/plugin"]; + var list = ["components/playback/playbackvalidation", "components/playback/playaccessvalidation", "components/playback/experimentalwarnings", "components/htmlaudioplayer/plugin", "components/htmlvideoplayer/plugin", "components/photoplayer/plugin", "components/youtubeplayer/plugin"]; if ("cordova" === self.appMode) { list.push("cordova/chromecast"); @@ -1176,10 +1176,10 @@ var AppInfo = {}; } if (appHost.supports("remotecontrol")) { - list.push("bower_components/emby-webcomponents/sessionplayer"); + list.push("components/sessionplayer"); if (browser.chrome || browser.opera) { - list.push("bower_components/emby-webcomponents/chromecast/chromecastplayer"); + list.push("components/chromecast/chromecastplayer"); } } @@ -1245,10 +1245,10 @@ var AppInfo = {}; }); if (!enableNativeGamepadKeyMapping() && isGamepadSupported()) { - require(["bower_components/emby-webcomponents/input/gamepadtokey"]); + require(["components/input/gamepadtokey"]); } - require(["bower_components/emby-webcomponents/thememediaplayer", "scripts/autobackdrops"]); + require(["components/thememediaplayer", "scripts/autobackdrops"]); if (!("cordova" !== self.appMode && "android" !== self.appMode)) { if (browser.android) { @@ -1259,15 +1259,15 @@ var AppInfo = {}; } if (!(browser.tv || browser.xboxOne || browser.ps4)) { - require(["bower_components/emby-webcomponents/nowplayingbar/nowplayingbar"]); + require(["components/nowplayingbar/nowplayingbar"]); } if (appHost.supports("remotecontrol")) { - require(["playerSelectionMenu", "bower_components/emby-webcomponents/playback/remotecontrolautoplay"]); + require(["playerSelectionMenu", "components/playback/remotecontrolautoplay"]); } if (!(appHost.supports("physicalvolumecontrol") && !browser.touch || browser.edge)) { - require(["bower_components/emby-webcomponents/playback/volumeosd"]); + require(["components/playback/volumeosd"]); } if (navigator.mediaSession) { @@ -1277,11 +1277,11 @@ var AppInfo = {}; require(["apiInput", "mouseManager"]); if (!(browser.tv || browser.xboxOne)) { - require(["bower_components/emby-webcomponents/playback/playbackorientation"]); + require(["components/playback/playbackorientation"]); registerServiceWorker(); if (window.Notification) { - require(["bower_components/emby-webcomponents/notifications/notifications"]); + require(["components/notifications/notifications"]); } } @@ -1345,7 +1345,7 @@ var AppInfo = {}; if (!window.Promise || browser.web0s) { initialDependencies.push(); - require(["bower_components/emby-webcomponents/native-promise-only/lib/npo.src"], init); + require(["components/native-promise-only/lib/npo.src"], init); } else { init(); } @@ -1357,7 +1357,7 @@ var AppInfo = {}; var urlArgs = "v=" + (window.dashboardVersion || new Date().getDate()); var bowerPath = getBowerPath(); var apiClientBowerPath = bowerPath + "/emby-apiclient"; - var embyWebComponentsBowerPath = bowerPath + "/emby-webcomponents"; + var embyWebComponentsBowerPath = "components"; var paths = { velocity: bowerPath + "/velocity/velocity.min", vibrant: bowerPath + "/vibrant/dist/vibrant", @@ -1502,8 +1502,8 @@ var AppInfo = {}; waitSeconds: 0, map: { "*": { - css: bowerPath + "/emby-webcomponents/require/requirecss", - text: bowerPath + "/emby-webcomponents/require/requiretext" + css: "components/require/requirecss", + text: "components/require/requiretext" } }, urlArgs: urlArgs, diff --git a/src/serviceworker.js b/src/serviceworker.js index fba101b81f..01cf8d63ef 100644 --- a/src/serviceworker.js +++ b/src/serviceworker.js @@ -1 +1 @@ -importScripts("bower_components/emby-webcomponents/serviceworker/notifications.js", "bower_components/emby-webcomponents/serviceworker/sync.js"); \ No newline at end of file +importScripts("components/serviceworker/notifications.js", "components/serviceworker/sync.js"); \ No newline at end of file From 8e1c56adf5955a9c809abbd05c71ed74cf2dd1d7 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 23 Feb 2019 18:26:35 +0000 Subject: [PATCH 018/220] removed bower_components from .gitignore --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index cb9b773756..ce35528e1f 100644 --- a/.gitignore +++ b/.gitignore @@ -71,9 +71,6 @@ coverage # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) .grunt -# Bower dependency directory (https://bower.io/) -bower_components - # node-waf configuration .lock-wscript From 2665923bb0b3ef8ae5d071b0b39d7063e75c6fc8 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 23 Feb 2019 19:14:56 +0000 Subject: [PATCH 019/220] merged alert and nativeAlert for webpack --- src/components/alert.js | 40 +++++++++++++++++++++++++++++ src/components/alert/alert.js | 34 ------------------------ src/components/alert/nativealert.js | 23 ----------------- src/scripts/site.js | 10 ++------ 4 files changed, 42 insertions(+), 65 deletions(-) create mode 100644 src/components/alert.js delete mode 100644 src/components/alert/alert.js delete mode 100644 src/components/alert/nativealert.js diff --git a/src/components/alert.js b/src/components/alert.js new file mode 100644 index 0000000000..0e8c16501f --- /dev/null +++ b/src/components/alert.js @@ -0,0 +1,40 @@ +define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize) { + 'use strict'; + + return function (text, title) { + + var options; + if (typeof text === 'string') { + options = { + title: title, + text: text + }; + } else { + options = text; + } + + if (browser.tv && window.alert) { + alert(replaceAll(options.text || '', '
', '\n')); + } else { + var items = []; + + items.push({ + name: globalize.translate('ButtonGotIt'), + id: 'ok', + type: 'submit' + }); + + options.buttons = items; + + return dialog(options).then(function (result) { + if (result === 'ok') { + return Promise.resolve(); + } + + return Promise.reject(); + }); + } + + return Promise.resolve(); + }; +}); \ No newline at end of file diff --git a/src/components/alert/alert.js b/src/components/alert/alert.js deleted file mode 100644 index ce434bac8a..0000000000 --- a/src/components/alert/alert.js +++ /dev/null @@ -1,34 +0,0 @@ -define(['dialog', 'globalize'], function (dialog, globalize) { - 'use strict'; - - return function (text, title) { - - var options; - if (typeof text === 'string') { - options = { - title: title, - text: text - }; - } else { - options = text; - } - - var items = []; - - items.push({ - name: globalize.translate('ButtonGotIt'), - id: 'ok', - type: 'submit' - }); - - options.buttons = items; - - return dialog(options).then(function (result) { - if (result === 'ok') { - return Promise.resolve(); - } - - return Promise.reject(); - }); - }; -}); \ No newline at end of file diff --git a/src/components/alert/nativealert.js b/src/components/alert/nativealert.js deleted file mode 100644 index f565e802c7..0000000000 --- a/src/components/alert/nativealert.js +++ /dev/null @@ -1,23 +0,0 @@ -define([], function () { - 'use strict'; - - function replaceAll(str, find, replace) { - - return str.split(find).join(replace); - } - - return function (options) { - - if (typeof options === 'string') { - options = { - text: options - }; - } - - var text = replaceAll(options.text || '', '
', '\n'); - - alert(text); - - return Promise.resolve(); - }; -}); \ No newline at end of file diff --git a/src/scripts/site.js b/src/scripts/site.js index 984c01800e..c42acb6325 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -465,8 +465,6 @@ var AppInfo = {}; define("apiclient", ["bower_components/emby-apiclient/apiclient"], returnFirstDependency); } - define("actionsheet", ["webActionSheet"], returnFirstDependency); - if ("registerElement" in document) { define("registerElement", []); } else { @@ -491,11 +489,7 @@ var AppInfo = {}; var preferNativeAlerts = browser.tv; - if (preferNativeAlerts && window.alert) { - define("alert", [embyWebComponentsBowerPath + "/alert/nativealert"], returnFirstDependency); - } else { - define("alert", [embyWebComponentsBowerPath + "/alert/alert"], returnFirstDependency); - } + define("alert", [embyWebComponentsBowerPath + "/alert"], returnFirstDependency); defineResizeObserver(); define("dialog", [embyWebComponentsBowerPath + "/dialog/dialog"], returnFirstDependency); @@ -1400,7 +1394,7 @@ var AppInfo = {}; paths.shaka = embyWebComponentsBowerPath + "/shaka/shaka-player.compiled"; define("chromecastHelper", [embyWebComponentsBowerPath + "/chromecast/chromecasthelpers"], returnFirstDependency); define("mediaSession", [embyWebComponentsBowerPath + "/playback/mediasession"], returnFirstDependency); - define("webActionSheet", [embyWebComponentsBowerPath + "/actionsheet/actionsheet"], returnFirstDependency); + define("actionsheet", [embyWebComponentsBowerPath + "/actionsheet/actionsheet"], returnFirstDependency); define("libjass", [bowerPath + "/libjass/libjass.min", "css!" + bowerPath + "/libjass/libjass"], returnFirstDependency); define("tunerPicker", ["components/tunerpicker"], returnFirstDependency); define("mainTabsManager", [embyWebComponentsBowerPath + "/maintabsmanager"], returnFirstDependency); From 3dba261ae7090b7c44660bea1b0e22325b07fe43 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 23 Feb 2019 19:34:34 +0000 Subject: [PATCH 020/220] define apiInput as a module for webpack --- .../{input/api.js => apiInput/apiInput.js} | 19 +++++++++++++++ .../{input => apiInput}/gamepadtokey.js | 0 .../mouse.js => apiInput/mouseManager.js} | 0 src/components/apiInput/package.json | 3 +++ src/scripts/site.js | 23 +------------------ 5 files changed, 23 insertions(+), 22 deletions(-) rename src/components/{input/api.js => apiInput/apiInput.js} (92%) rename src/components/{input => apiInput}/gamepadtokey.js (100%) rename src/components/{input/mouse.js => apiInput/mouseManager.js} (100%) create mode 100644 src/components/apiInput/package.json diff --git a/src/components/input/api.js b/src/components/apiInput/apiInput.js similarity index 92% rename from src/components/input/api.js rename to src/components/apiInput/apiInput.js index c3be61e2e2..e6cb3d312c 100644 --- a/src/components/input/api.js +++ b/src/components/apiInput/apiInput.js @@ -234,6 +234,19 @@ define(['connectionManager', 'playbackManager', 'events', 'inputManager', 'focus events.on(apiClient, "message", onMessageReceived); } + function enableNativeGamepadKeyMapping() { + if (!(!window.navigator || "string" != typeof window.navigator.gamepadInputEmulation)) { + window.navigator.gamepadInputEmulation = "keyboard"; + return true; + } + + return false; + } + + function isGamepadSupported() { + return "ongamepadconnected" in window || navigator.getGamepads || navigator.webkitGetGamepads; + } + connectionManager.getApiClients().forEach(bindEvents); events.on(connectionManager, 'apiclientcreated', function (e, newApiClient) { @@ -241,5 +254,11 @@ define(['connectionManager', 'playbackManager', 'events', 'inputManager', 'focus bindEvents(newApiClient); }); + if (!enableNativeGamepadKeyMapping() && isGamepadSupported()) { + require(["components/apiInput/gamepadtokey"]); + } + + require(["components/apiInput/mouseManager"]); + return serverNotifications; }); diff --git a/src/components/input/gamepadtokey.js b/src/components/apiInput/gamepadtokey.js similarity index 100% rename from src/components/input/gamepadtokey.js rename to src/components/apiInput/gamepadtokey.js diff --git a/src/components/input/mouse.js b/src/components/apiInput/mouseManager.js similarity index 100% rename from src/components/input/mouse.js rename to src/components/apiInput/mouseManager.js diff --git a/src/components/apiInput/package.json b/src/components/apiInput/package.json new file mode 100644 index 0000000000..6c542951b2 --- /dev/null +++ b/src/components/apiInput/package.json @@ -0,0 +1,3 @@ +{ + "main": "apiInput.js" +} \ No newline at end of file diff --git a/src/scripts/site.js b/src/scripts/site.js index c42acb6325..8035c898ff 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1198,19 +1198,6 @@ var AppInfo = {}; }); } - function enableNativeGamepadKeyMapping() { - if (!(!window.navigator || "string" != typeof window.navigator.gamepadInputEmulation)) { - window.navigator.gamepadInputEmulation = "keyboard"; - return true; - } - - return false; - } - - function isGamepadSupported() { - return "ongamepadconnected" in window || navigator.getGamepads || navigator.webkitGetGamepads; - } - function onAppReady(browser) { console.log("Begin onAppReady"); @@ -1238,10 +1225,6 @@ var AppInfo = {}; hashbang: true }); - if (!enableNativeGamepadKeyMapping() && isGamepadSupported()) { - require(["components/input/gamepadtokey"]); - } - require(["components/thememediaplayer", "scripts/autobackdrops"]); if (!("cordova" !== self.appMode && "android" !== self.appMode)) { @@ -1268,8 +1251,6 @@ var AppInfo = {}; require(["mediaSession"]); } - require(["apiInput", "mouseManager"]); - if (!(browser.tv || browser.xboxOne)) { require(["components/playback/playbackorientation"]); registerServiceWorker(); @@ -1471,7 +1452,6 @@ var AppInfo = {}; define("cardBuilder", [embyWebComponentsBowerPath + "/cardbuilder/cardbuilder"], returnFirstDependency); define("peoplecardbuilder", [embyWebComponentsBowerPath + "/cardbuilder/peoplecardbuilder"], returnFirstDependency); define("chaptercardbuilder", [embyWebComponentsBowerPath + "/cardbuilder/chaptercardbuilder"], returnFirstDependency); - define("mouseManager", [embyWebComponentsBowerPath + "/input/mouse"], returnFirstDependency); define("flexStyles", ["css!" + embyWebComponentsBowerPath + "/flexstyles"], returnFirstDependency); define("deleteHelper", [embyWebComponentsBowerPath + "/deletehelper"], returnFirstDependency); define("tvguide", [embyWebComponentsBowerPath + "/guide/guide"], returnFirstDependency); @@ -1570,8 +1550,7 @@ var AppInfo = {}; define("fnchecked", ["legacy/fnchecked"], returnFirstDependency); define("dialogHelper", [embyWebComponentsBowerPath + "/dialoghelper/dialoghelper"], returnFirstDependency); define("inputmanager", ["inputManager"], returnFirstDependency); - define("apiInput", [embyWebComponentsBowerPath + "/input/api"], returnFirstDependency); - define("serverNotifications", ["apiInput"], returnFirstDependency); + define("serverNotifications", [embyWebComponentsBowerPath + "/apiInput/apiInput"], returnFirstDependency); define("headroom-window", ["headroom"], createWindowHeadroom); define("appFooter-shared", ["appFooter"], createSharedAppFooter); define("skinManager", [embyWebComponentsBowerPath + "/skinmanager"], function (skinManager) { From e45e8d3f00e359c1c28f69b0d7f418a87fb29e10 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 23 Feb 2019 19:34:50 +0000 Subject: [PATCH 021/220] add missing package.json for module actionsheet --- src/components/actionsheet/package.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/components/actionsheet/package.json diff --git a/src/components/actionsheet/package.json b/src/components/actionsheet/package.json new file mode 100644 index 0000000000..622f1e075d --- /dev/null +++ b/src/components/actionsheet/package.json @@ -0,0 +1,3 @@ +{ + "main": "actionsheet.js" +} \ No newline at end of file From 134bbbf6c0ea95bbb85234435c89952779483ffd Mon Sep 17 00:00:00 2001 From: Sparky Date: Sat, 23 Feb 2019 13:30:49 -0500 Subject: [PATCH 022/220] Fix volume slider not working on nowplayingbar Turns out, by wrapping the code in a function it takes the necessary bits out of scope, causing the nowplayingbar to become non-functional when it comes to adjusting volume. Fixes https://github.com/jellyfin/jellyfin/issues/988 --- .gitignore | 3 --- .../emby-webcomponents/nowplayingbar/nowplayingbar.js | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index ac62bd07a1..4895d21b80 100644 --- a/.gitignore +++ b/.gitignore @@ -71,9 +71,6 @@ coverage # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) .grunt -# Bower dependency directory (https://bower.io/) -bower_components - # node-waf configuration .lock-wscript diff --git a/src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.js b/src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.js index 331b178b39..481155d3b7 100644 --- a/src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.js +++ b/src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.js @@ -191,9 +191,9 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader', currentPlayer.setVolume(this.value); } } - volumeSlider.addEventListener('change', setVolume.bind(this)); - volumeSlider.addEventListener('mousemove', setVolume.bind(this)); - volumeSlider.addEventListener('touchmove', setVolume.bind(this)); + volumeSlider.addEventListener('change', setVolume); + volumeSlider.addEventListener('mousemove', setVolume); + volumeSlider.addEventListener('touchmove', setVolume); positionSlider = elem.querySelector('.nowPlayingBarPositionSlider'); From ae9c0a77f70f3478db4be6701d0265d068572242 Mon Sep 17 00:00:00 2001 From: redSpoutnik <15638041+redSpoutnik@users.noreply.github.com> Date: Sun, 24 Feb 2019 10:53:41 +0100 Subject: [PATCH 023/220] Go back on Media stop --- src/components/remotecontrol.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/remotecontrol.js b/src/components/remotecontrol.js index 58e69961e7..76f0d673d0 100644 --- a/src/components/remotecontrol.js +++ b/src/components/remotecontrol.js @@ -429,6 +429,7 @@ define(["browser", "datetime", "backdrop", "libraryBrowser", "listView", "imageL if (!state.NextMediaType) { updatePlayerState(player, dlg, {}); loadPlaylist(dlg); + Emby.Page.back(); } } From fa8eb4f34d984a37e83dbdde6ffc9575b2de29ea Mon Sep 17 00:00:00 2001 From: dkanada Date: Tue, 26 Feb 2019 02:39:58 +0900 Subject: [PATCH 024/220] method deminification --- src/scripts/pluginspage.js | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/scripts/pluginspage.js b/src/scripts/pluginspage.js index 69583403e8..37fcfd423a 100644 --- a/src/scripts/pluginspage.js +++ b/src/scripts/pluginspage.js @@ -32,12 +32,34 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-linkbut function getPluginCardHtml(plugin, pluginConfigurationPages) { var configPage = pluginConfigurationPages.filter(function(pluginConfigurationPage) { return pluginConfigurationPage.PluginId == plugin.Id - })[0], - html = "", - disallowPlugins = !Dashboard.allowPluginPages(plugin.Id), - configPageUrl = configPage ? Dashboard.getConfigurationPageUrl(configPage.Name) : null, - href = configPage && !disallowPlugins ? configPageUrl : null; - return html += "
", html += '
', html += '
', html += '
', html += href ? '' : configPageUrl ? disallowPlugins ? '
' : '", html += '
', html += '
', html += '', html += "
", html += "
", html += configPage ? configPage.DisplayName || plugin.Name : plugin.Name, html += "
", html += "
", html += plugin.Version, html += "
", html += "
", html += "
", html += "
" + })[0]; + var html = ""; + var disallowPlugins = !Dashboard.allowPluginPages(plugin.Id); + var configPageUrl = configPage ? Dashboard.getConfigurationPageUrl(configPage.Name) : null; + var href = configPage && !disallowPlugins ? configPageUrl : null; + + html += "
"; + html += '
'; + html += '
'; + html += '
'; + html += href ? '' : configPageUrl ? disallowPlugins ? '
' : '"; + html += '
'; + html += '
'; + html += ''; + html += "
"; + html += "
"; + html += configPage ? configPage.DisplayName || plugin.Name : plugin.Name; + html += "
"; + html += "
"; + html += plugin.Version; + html += "
"; + html += "
"; + html += "
"; + html += "
"; + return html; } function renderPlugins(page, plugins, showNoPluginsMessage) { From 2dd44178fa9dbe1f8239fd5be926ffa8b563b018 Mon Sep 17 00:00:00 2001 From: dkanada Date: Tue, 26 Feb 2019 02:56:18 +0900 Subject: [PATCH 025/220] remove plugin configuration block for android devices --- src/scripts/librarymenu.js | 17 +++++++---------- src/scripts/pluginspage.js | 8 +++----- src/scripts/site.js | 3 --- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index 8d65f9420b..145ae42479 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -386,16 +386,13 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " function addPluginPagesToMainMenu(links, pluginItems, section) { for (var i = 0, length = pluginItems.length; i < length; i++) { var pluginItem = pluginItems[i]; - - if (Dashboard.allowPluginPages(pluginItem.PluginId)) { - if (pluginItem.EnableInMainMenu && pluginItem.MenuSection === section) { - links.push({ - name: pluginItem.DisplayName, - icon: pluginItem.MenuIcon || "folder", - href: Dashboard.getConfigurationPageUrl(pluginItem.Name), - pageUrls: [Dashboard.getConfigurationPageUrl(pluginItem.Name)] - }); - } + if (pluginItem.EnableInMainMenu && pluginItem.MenuSection === section) { + links.push({ + name: pluginItem.DisplayName, + icon: pluginItem.MenuIcon || "folder", + href: Dashboard.getConfigurationPageUrl(pluginItem.Name), + pageUrls: [Dashboard.getConfigurationPageUrl(pluginItem.Name)] + }); } } } diff --git a/src/scripts/pluginspage.js b/src/scripts/pluginspage.js index 37fcfd423a..6fd82f4a2d 100644 --- a/src/scripts/pluginspage.js +++ b/src/scripts/pluginspage.js @@ -33,18 +33,16 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-linkbut var configPage = pluginConfigurationPages.filter(function(pluginConfigurationPage) { return pluginConfigurationPage.PluginId == plugin.Id })[0]; - var html = ""; - var disallowPlugins = !Dashboard.allowPluginPages(plugin.Id); var configPageUrl = configPage ? Dashboard.getConfigurationPageUrl(configPage.Name) : null; - var href = configPage && !disallowPlugins ? configPageUrl : null; + var html = ""; html += "
"; html += '
'; html += '
'; html += '
'; - html += href ? '' : configPageUrl ? disallowPlugins ? '
' : '"; html += '
'; html += '
'; diff --git a/src/scripts/site.js b/src/scripts/site.js index 573464ec2c..c387952a9f 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -32,9 +32,6 @@ function pageIdOn(eventName, id, fn) { }) } var Dashboard = { - allowPluginPages: function(pluginId) { - return true; - }, getCurrentUser: function() { return window.ApiClient.getCurrentUser(!1) }, From 3f7ca1d915e98621af92455e365e83ae2197164f Mon Sep 17 00:00:00 2001 From: dkanada Date: Tue, 26 Feb 2019 03:15:12 +0900 Subject: [PATCH 026/220] clean up plugin catalog page --- src/scripts/plugincatalogpage.js | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/scripts/plugincatalogpage.js b/src/scripts/plugincatalogpage.js index ed237a02d4..40d57560b5 100644 --- a/src/scripts/plugincatalogpage.js +++ b/src/scripts/plugincatalogpage.js @@ -3,7 +3,6 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-linkbutton", " function reloadList(page) { loading.show(); - query.IsAppStoreSafe = true; var promise1 = ApiClient.getAvailablePlugins(query); var promise2 = ApiClient.getInstalledPlugins(); Promise.all([promise1, promise2]).then(function (responses) { @@ -16,13 +15,8 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-linkbutton", " }); } - function populateList(options) { - populateListInternal(options); - } - function getHeaderText(category) { category = category.replace(" ", ""); - if ("Channel" === category) { category = "Channels"; } else if ("Theme" === category) { @@ -36,11 +30,7 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-linkbutton", " return globalize.translate(category); } - function isUserInstalledPlugin(plugin) { - return -1 === ["02528C96-F727-44D7-BE87-9EEF040758C3", "0277E613-3EC0-4360-A3DE-F8AF0AABB5E9", "4DCB591C-0FA2-4C5D-A7E5-DABE37164C8B"].indexOf(plugin.guid); - } - - function populateListInternal(options) { + function populateList(options) { var availablePlugins = options.availablePlugins; var installedPlugins = options.installedPlugins; var allPlugins = availablePlugins.filter(function (plugin) { @@ -113,7 +103,7 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-linkbutton", " } return 0; - }).filter(isUserInstalledPlugin); + }); html += '
'; var limit = screen.availWidth >= 1920 ? 15 : 12; @@ -215,11 +205,14 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-linkbutton", " var query = { TargetSystems: "Server", + IsAppStoreSafe: true, IsAdult: false }; + window.PluginCatalog = { renderCatalog: populateList }; + return function (view, params) { view.querySelector("#selectSystem").addEventListener("change", function () { query.TargetSystems = this.value; From 32a8e89420308ebce74031d659cf9db5bd3ca106 Mon Sep 17 00:00:00 2001 From: dkanada Date: Wed, 27 Feb 2019 06:11:42 +0900 Subject: [PATCH 027/220] use normal method for getAvailablePlugins --- src/scripts/site.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index c387952a9f..2d6c15b1eb 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -150,14 +150,8 @@ var Dashboard = { ! function() { "use strict"; - function initializeApiClient(apiClient) { - "cordova" !== self.appMode && "android" !== self.appMode || (apiClient.getAvailablePlugins = function() { - return Promise.resolve([]) - }) - } - function onApiClientCreated(e, newApiClient) { - initializeApiClient(newApiClient), window.$ && ($.ajax = newApiClient.ajax) + window.$ && ($.ajax = newApiClient.ajax) } function defineConnectionManager(connectionManager) { From bb118a5ae8e09361a46a79721de8119734e17f76 Mon Sep 17 00:00:00 2001 From: Vasily Date: Tue, 26 Feb 2019 21:12:58 +0000 Subject: [PATCH 028/220] add suggested changes from code review Co-Authored-By: dkanada --- src/scripts/pluginspage.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/scripts/pluginspage.js b/src/scripts/pluginspage.js index 6fd82f4a2d..6264f012e0 100644 --- a/src/scripts/pluginspage.js +++ b/src/scripts/pluginspage.js @@ -41,7 +41,12 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-linkbut html += '"; html += '
'; @@ -137,4 +142,4 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-linkbut }), window.PluginsPage = { renderPlugins: renderPlugins } -}); \ No newline at end of file +}); From 0b099806a7acab1ae62dadb1312605bb776d461b Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Thu, 28 Feb 2019 21:41:24 +0000 Subject: [PATCH 029/220] fix merge conflicts --- src/scripts/site.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 4752d59235..3f40ae07df 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -54,9 +54,6 @@ function pageIdOn(eventName, id, fn) { } var Dashboard = { - allowPluginPages: function (pluginId) { - return true; - }, getCurrentUser: function () { return window.ApiClient.getCurrentUser(false); }, From ba2c777772533c3095cf19f16776100bf60ea1a2 Mon Sep 17 00:00:00 2001 From: PloughPuff Date: Fri, 8 Feb 2019 13:16:30 +0000 Subject: [PATCH 030/220] Always show FFmpeg path in Transcoding page Removed the 'hide' and 'required' settings from the html to always show the FFmpeg path to user and also allow user to remove a custom path and return to using whatever is available from system $PATH. --- src/encodingsettings.html | 4 ++-- src/scripts/encodingsettings.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/encodingsettings.html b/src/encodingsettings.html index cc4b2360ed..ae0cd83cf6 100644 --- a/src/encodingsettings.html +++ b/src/encodingsettings.html @@ -91,10 +91,10 @@
${LabelTranscodingThreadCountHelp}
-
+
- +
diff --git a/src/scripts/encodingsettings.js b/src/scripts/encodingsettings.js index 7a2461a6bb..392ec22250 100644 --- a/src/scripts/encodingsettings.js +++ b/src/scripts/encodingsettings.js @@ -90,8 +90,8 @@ define(["jQuery", "loading", "globalize", "dom"], function($, loading, globalize var page = this; ApiClient.getNamedConfiguration("encoding").then(function(config) { ApiClient.getSystemInfo().then(function(systemInfo) { - "External" == systemInfo.EncoderLocationType ? (page.querySelector(".fldEncoderPath").classList.add("hide"), page.querySelector(".txtEncoderPath").removeAttribute("required")) : (page.querySelector(".fldEncoderPath").classList.remove("hide"), page.querySelector(".txtEncoderPath").setAttribute("required", "required")), loadPage(page, config, systemInfo) + loadPage(page, config, systemInfo) }) }) }) -}); \ No newline at end of file +}); From 037059f59d63494b2c5fd742900c5dce0479954c Mon Sep 17 00:00:00 2001 From: PloughPuff Date: Thu, 28 Feb 2019 22:10:49 +0000 Subject: [PATCH 031/220] Use EncoderAppPathDisplay to populate encoder path field --- src/scripts/encodingsettings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/encodingsettings.js b/src/scripts/encodingsettings.js index 392ec22250..88e08f87d3 100644 --- a/src/scripts/encodingsettings.js +++ b/src/scripts/encodingsettings.js @@ -4,7 +4,7 @@ define(["jQuery", "loading", "globalize", "dom"], function($, loading, globalize function loadPage(page, config, systemInfo) { Array.prototype.forEach.call(page.querySelectorAll(".chkDecodeCodec"), function(c) { c.checked = -1 !== (config.HardwareDecodingCodecs || []).indexOf(c.getAttribute("data-codec")) - }), page.querySelector("#chkHardwareEncoding").checked = config.EnableHardwareEncoding, $("#selectVideoDecoder", page).val(config.HardwareAccelerationType), $("#selectThreadCount", page).val(config.EncodingThreadCount), $("#txtDownMixAudioBoost", page).val(config.DownMixAudioBoost), page.querySelector(".txtEncoderPath").value = config.EncoderAppPath || "", $("#txtTranscodingTempPath", page).val(config.TranscodingTempPath || ""), $("#txtVaapiDevice", page).val(config.VaapiDevice || ""), page.querySelector("#selectH264Preset").value = config.H264Preset || "", page.querySelector("#txtH264Crf").value = config.H264Crf || "", page.querySelector("#chkEnableSubtitleExtraction").checked = config.EnableSubtitleExtraction || !1, page.querySelector("#selectVideoDecoder").dispatchEvent(new CustomEvent("change", { + }), page.querySelector("#chkHardwareEncoding").checked = config.EnableHardwareEncoding, $("#selectVideoDecoder", page).val(config.HardwareAccelerationType), $("#selectThreadCount", page).val(config.EncodingThreadCount), $("#txtDownMixAudioBoost", page).val(config.DownMixAudioBoost), page.querySelector(".txtEncoderPath").value = config.EncoderAppPathDisplay || "", $("#txtTranscodingTempPath", page).val(config.TranscodingTempPath || ""), $("#txtVaapiDevice", page).val(config.VaapiDevice || ""), page.querySelector("#selectH264Preset").value = config.H264Preset || "", page.querySelector("#txtH264Crf").value = config.H264Crf || "", page.querySelector("#chkEnableSubtitleExtraction").checked = config.EnableSubtitleExtraction || !1, page.querySelector("#selectVideoDecoder").dispatchEvent(new CustomEvent("change", { bubbles: !0 })), loading.hide() } From 9878cfc012660688472454e66e812b903714fc52 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Mon, 4 Mar 2019 20:25:42 +0000 Subject: [PATCH 032/220] Update src/scripts/site.js It's really a matter of preference, but if you want it this way, np. Co-Authored-By: vitorsemeano --- src/scripts/site.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 3f40ae07df..f810f8c0e1 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -271,7 +271,7 @@ var AppInfo = {}; function createConnectionManager() { return require(["connectionManagerFactory", "apphost", "credentialprovider", "events", "userSettings"], function (ConnectionManager, apphost, credentialProvider, events, userSettings) { var credentialProviderInstance = new credentialProvider(), - promises = [apphost.getSyncProfile(), apphost.init()]; + var promises = [apphost.getSyncProfile(), apphost.init()]; Promise.all(promises).then(function (responses) { var deviceProfile = responses[0], From 24ae3a9c4904a72d62f14327f3735778637d9e5a Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Mon, 4 Mar 2019 20:27:29 +0000 Subject: [PATCH 033/220] Update src/scripts/site.js updating as suggested Co-Authored-By: vitorsemeano --- src/scripts/site.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index f810f8c0e1..a9868d05f8 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -293,7 +293,7 @@ var AppInfo = {}; var apiClient = new apiClientFactory(Dashboard.serverAddress(), apphost.appName(), apphost.appVersion(), apphost.deviceName(), apphost.deviceId(), window.devicePixelRatio); apiClient.enableAutomaticNetworking = false; - apiClient.manualAddressOnly = true; + apiClient.manualAddressOnly = true; connectionManager.addApiClient(apiClient); From 5a258d65228198c7593d08391762248b7be1a1c2 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Mon, 4 Mar 2019 20:30:42 +0000 Subject: [PATCH 034/220] adjust var declarations for some specific cases --- src/scripts/site.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index f810f8c0e1..fbc7804af1 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -270,12 +270,12 @@ var AppInfo = {}; function createConnectionManager() { return require(["connectionManagerFactory", "apphost", "credentialprovider", "events", "userSettings"], function (ConnectionManager, apphost, credentialProvider, events, userSettings) { - var credentialProviderInstance = new credentialProvider(), + var credentialProviderInstance = new credentialProvider(); var promises = [apphost.getSyncProfile(), apphost.init()]; Promise.all(promises).then(function (responses) { - var deviceProfile = responses[0], - capabilities = Dashboard.capabilities(apphost); + var deviceProfile = responses[0]; + var capabilities = Dashboard.capabilities(apphost); capabilities.DeviceProfile = deviceProfile; From b50647f101954d23beaeeaaf3f6330a03d5b5580 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Mon, 4 Mar 2019 20:36:51 +0000 Subject: [PATCH 035/220] fix nested if else not done properly with deuglify --- src/scripts/site.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index a6f34e9769..a56e1883b6 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -456,12 +456,10 @@ var AppInfo = {}; if ("registerElement" in document) { define("registerElement", []); + } else if (browser.msie) { + define("registerElement", [bowerPath + "/webcomponentsjs/webcomponents-lite.min.js"], returnFirstDependency); } else { - if (browser.msie) { - define("registerElement", [bowerPath + "/webcomponentsjs/webcomponents-lite.min.js"], returnFirstDependency); - } else { - define("registerElement", [bowerPath + "/document-register-element/build/document-register-element"], returnFirstDependency); - } + define("registerElement", [bowerPath + "/document-register-element/build/document-register-element"], returnFirstDependency); } if ("cordova" === self.appMode || "android" === self.appMode) { From e60da6b54551be1b29915975df3a72f1fa2c8235 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Mon, 4 Mar 2019 20:38:39 +0000 Subject: [PATCH 036/220] renamed strange variable names --- src/scripts/site.js | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index a56e1883b6..f02e63a221 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -32,11 +32,11 @@ function getParameterByName(name, url) { function pageClassOn(eventName, className, fn) { "use strict"; - document.addEventListener(eventName, function (e__q) { - var target = e__q.target; + document.addEventListener(eventName, function (event) { + var target = event.target; if (target.classList.contains(className)) { - fn.call(target, e__q); + fn.call(target, event); } }); } @@ -44,11 +44,11 @@ function pageClassOn(eventName, className, fn) { function pageIdOn(eventName, id, fn) { "use strict"; - document.addEventListener(eventName, function (e__w) { - var target = e__w.target; + document.addEventListener(eventName, function (event) { + var target = event.target; if (target.id === id) { - fn.call(target, e__w); + fn.call(target, event); } }); } @@ -336,7 +336,7 @@ var AppInfo = {}; } function getPlaybackManager(playbackManager) { - window.addEventListener("beforeunload", function (e__r) { + window.addEventListener("beforeunload", function () { try { playbackManager.onAppClose(); } catch (err) { @@ -523,19 +523,15 @@ var AppInfo = {}; define("bgtaskregister", ["environments/windows-uwp/bgtaskregister"], returnFirstDependency); define("transfermanager", ["environments/windows-uwp/transfermanager"], returnFirstDependency); define("filerepository", ["environments/windows-uwp/filerepository"], returnFirstDependency); + } else if ("cordova" === self.appMode) { + define("filerepository", ["cordova/filerepository"], returnFirstDependency); + define("transfermanager", ["filerepository"], returnFirstDependency); + } else if ("android" === self.appMode) { + define("transfermanager", ["cordova/transfermanager"], returnFirstDependency); + define("filerepository", ["cordova/filerepository"], returnFirstDependency); } else { - if ("cordova" === self.appMode) { - define("filerepository", ["cordova/filerepository"], returnFirstDependency); - define("transfermanager", ["filerepository"], returnFirstDependency); - } else { - if ("android" === self.appMode) { - define("transfermanager", ["cordova/transfermanager"], returnFirstDependency); - define("filerepository", ["cordova/filerepository"], returnFirstDependency); - } else { - define("transfermanager", [apiClientBowerPath + "/sync/transfermanager"], returnFirstDependency); - define("filerepository", [apiClientBowerPath + "/sync/filerepository"], returnFirstDependency); - } - } + define("transfermanager", [apiClientBowerPath + "/sync/transfermanager"], returnFirstDependency); + define("filerepository", [apiClientBowerPath + "/sync/filerepository"], returnFirstDependency); } if ("android" === self.appMode) { @@ -591,10 +587,10 @@ var AppInfo = {}; function loadCoreDictionary(globalize) { var languages = ["ar", "be-by", "bg-bg", "ca", "cs", "da", "de", "el", "en-gb", "en-us", "es", "es-ar", "es-mx", "fa", "fi", "fr", "fr-ca", "gsw", "he", "hi-in", "hr", "hu", "id", "it", "kk", "ko", "lt-lt", "ms", "nb", "nl", "pl", "pt-br", "pt-pt", "ro", "ru", "sk", "sl-si", "sv", "tr", "uk", "vi", "zh-cn", "zh-hk", "zh-tw"]; - var translations = languages.map(function (i__t) { + var translations = languages.map(function (language) { return { - lang: i__t, - path: "strings/" + i__t + ".json" + lang: language, + path: "strings/" + language + ".json" }; }); globalize.defaultModule("core"); @@ -1168,8 +1164,8 @@ var AppInfo = {}; } } - for (var i__y = 0, length = externalPlugins.length; i__y < length; i__y++) { - list.push(externalPlugins[i__y]); + for (var index = 0, length = externalPlugins.length; index < length; index++) { + list.push(externalPlugins[index]); } return new Promise(function (resolve, reject) { From 1dd3096f377f04b9a8c84163a54a9aa9b6d3f909 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Mon, 4 Mar 2019 20:40:13 +0000 Subject: [PATCH 037/220] Update src/scripts/site.js i agree, definitely more readable Co-Authored-By: vitorsemeano --- src/scripts/site.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index f02e63a221..3773e8896b 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1146,7 +1146,15 @@ var AppInfo = {}; function loadPlugins(externalPlugins, appHost, browser, shell) { console.log("Loading installed plugins"); - var list = ["bower_components/emby-webcomponents/playback/playbackvalidation", "bower_components/emby-webcomponents/playback/playaccessvalidation", "bower_components/emby-webcomponents/playback/experimentalwarnings", "bower_components/emby-webcomponents/htmlaudioplayer/plugin", "bower_components/emby-webcomponents/htmlvideoplayer/plugin", "bower_components/emby-webcomponents/photoplayer/plugin", "bower_components/emby-webcomponents/youtubeplayer/plugin"]; + var list = [ + "bower_components/emby-webcomponents/playback/playbackvalidation", + "bower_components/emby-webcomponents/playback/playaccessvalidation", + "bower_components/emby-webcomponents/playback/experimentalwarnings", + "bower_components/emby-webcomponents/htmlaudioplayer/plugin", + "bower_components/emby-webcomponents/htmlvideoplayer/plugin", + "bower_components/emby-webcomponents/photoplayer/plugin", + "bower_components/emby-webcomponents/youtubeplayer/plugin" + ]; if ("cordova" === self.appMode) { list.push("cordova/chromecast"); From 6a15acb310a503cfc4081c56bf6b85b45650659e Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Mon, 4 Mar 2019 20:43:37 +0000 Subject: [PATCH 038/220] Update src/scripts/site.js well the tool can't make all the coding, am i right? Co-Authored-By: vitorsemeano --- src/scripts/site.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 3773e8896b..69dfe6703d 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1194,7 +1194,7 @@ var AppInfo = {}; } function enableNativeGamepadKeyMapping() { - if (!(!window.navigator || "string" != typeof window.navigator.gamepadInputEmulation)) { + if (window.navigator && "string" == typeof window.navigator.gamepadInputEmulation) { window.navigator.gamepadInputEmulation = "keyboard"; return true; } From ff07a77133848af8faf79fea84dfbae42c96cfa5 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Mon, 4 Mar 2019 20:44:27 +0000 Subject: [PATCH 039/220] Update src/scripts/site.js Co-Authored-By: vitorsemeano --- src/scripts/site.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 69dfe6703d..527b71175d 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1239,7 +1239,7 @@ var AppInfo = {}; require(["bower_components/emby-webcomponents/thememediaplayer", "scripts/autobackdrops"]); - if (!("cordova" !== self.appMode && "android" !== self.appMode)) { + if ("cordova" === self.appMode || "android" === self.appMode) { if (browser.android) { require(["cordova/mediasession", "cordova/chromecast", "cordova/appshortcuts"]); } else if (browser.safari) { From 8d7fa1557f66d4cd9aab8d3a7d86efc83a9d94f2 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Mon, 4 Mar 2019 20:45:19 +0000 Subject: [PATCH 040/220] Update src/scripts/site.js Co-Authored-By: vitorsemeano --- src/scripts/site.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 527b71175d..5ce5328139 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1247,7 +1247,7 @@ var AppInfo = {}; } } - if (!(browser.tv || browser.xboxOne || browser.ps4)) { + if (!browser.tv && !browser.xboxOne && !browser.ps4) { require(["bower_components/emby-webcomponents/nowplayingbar/nowplayingbar"]); } From 64c3c15af4605e5e740edac6287874e86b72fee4 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Mon, 4 Mar 2019 20:45:44 +0000 Subject: [PATCH 041/220] Update src/scripts/site.js Co-Authored-By: vitorsemeano --- src/scripts/site.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 5ce5328139..e9843f90f2 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1265,7 +1265,7 @@ var AppInfo = {}; require(["apiInput", "mouseManager"]); - if (!(browser.tv || browser.xboxOne)) { + if (!browser.tv && !browser.xboxOne) { require(["bower_components/emby-webcomponents/playback/playbackorientation"]); registerServiceWorker(); From 7e22a64238453ea6d97965d35c8759eb12a85f5d Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Mon, 4 Mar 2019 20:47:00 +0000 Subject: [PATCH 042/220] merging ifs --- src/scripts/site.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index f02e63a221..61f3a36c83 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1276,10 +1276,8 @@ var AppInfo = {}; initLocalSyncEvents(); } - if (!AppInfo.isNativeApp) { - if (window.ApiClient) { - require(["css!" + ApiClient.getUrl("Branding/Css")]); - } + if (!AppInfo.isNativeApp && window.ApiClient) { + require(["css!" + ApiClient.getUrl("Branding/Css")]); } }); } From 3def2a935de21b0d140bc38cf8760e3a398e5abe Mon Sep 17 00:00:00 2001 From: dkanada Date: Tue, 5 Mar 2019 20:42:12 +0900 Subject: [PATCH 043/220] move metadata manager to navbar and out of server configuration --- src/scripts/librarymenu.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index 145ae42479..395834f9d8 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -189,6 +189,7 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " html += globalize.translate("HeaderAdmin"); html += ""; html += 'dashboard' + globalize.translate("TabDashboard") + ""; + html += 'mode_edit' + globalize.translate("MetadataManager") + ""; html += "
"; } @@ -271,7 +272,7 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " pageIds: ["dashboardPage", "serverActivityPage"], icon: "dashboard" }, { - name: globalize.translate("TabSettings"), + name: globalize.translate("General"), href: "dashboardgeneral.html", pageIds: ["dashboardGeneralPage"], icon: "settings" @@ -373,12 +374,6 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " pageIds: ["scheduledTasksPage", "scheduledTaskPage"], icon: "schedule" }); - links.push({ - name: globalize.translate("MetadataManager"), - href: "edititemmetadata.html", - pageIds: [], - icon: "mode_edit" - }); addPluginPagesToMainMenu(links, pluginItems); return links; } From 89be94fff347e9a3b2e129be5ed8006e6e956a31 Mon Sep 17 00:00:00 2001 From: xlinbsd Date: Tue, 5 Mar 2019 13:09:32 +0100 Subject: [PATCH 044/220] Better progressive playback controls of bottom pages (#164) * Allow volume change on shrinker width screenview * Tiny better width compromise in width control fluidity * Better progressive music control panel * Delay hiding of album image displayed * Wider volume slider --- .../nowplayingbar/nowplayingbar.css | 54 ++++++++++++++----- .../nowplayingbar/nowplayingbar.js | 2 +- src/css/nowplaying.css | 22 ++++++-- src/css/videoosd.css | 11 ++-- 4 files changed, 67 insertions(+), 22 deletions(-) diff --git a/src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.css b/src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.css index 1392541e16..80f078d880 100644 --- a/src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.css +++ b/src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.css @@ -119,38 +119,66 @@ height: 1.2em !important; } -@media all and (max-width: 87.5em) { - .nowPlayingBarUserDataButtons { +@media all and (max-width: 70em) { + + .nowPlayingBarRight .nowPlayingBarUserDataButtons { display: none; } } -@media all and (max-width: 68.75em) { - - .nowPlayingBarVolumeSliderContainer, .nowPlayingBar .muteButton, .nowPlayingBar .unmuteButton { +@media all and (max-width: 66em) { + .toggleRepeatButton { display: none !important; } } -@media all and (max-width: 50em) { + +@media all and (max-width: 62em) { + + .nowPlayingBarCenter .nowPlayingBarCurrentTime { + display: none !important; + } + +} + +@media all and (max-width: 56em) { .nowPlayingBarCenter { display: none !important; } - .toggleRepeatButton { - display: none; - } } -@media all and (min-width: 50em) { + +@media all and (min-width: 56em) { .nowPlayingBarRight .playPauseButton { display: none; } - .nowPlayingBarInfoContainer { - max-width: 40%; - } +} + +@media all and (max-width: 40em) { + + .nowPlayingBarInfoContainer .nowPlayingImage { + display: none; + } + +} + +@media all and (max-width: 36em) { + + .nowPlayingBarRight .nowPlayingBarVolumeSliderContainer { + display: none !important; + } + +} + +@media all and (max-width: 24em) { + + .nowPlayingBar .muteButton, .nowPlayingBar .unmuteButton { + display: none; + } + } diff --git a/src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.js b/src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.js index 481155d3b7..01c920a501 100644 --- a/src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.js +++ b/src/bower_components/emby-webcomponents/nowplayingbar/nowplayingbar.js @@ -56,7 +56,7 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader', html += ''; - html += '
'; + html += '
'; html += ''; html += '
'; diff --git a/src/css/nowplaying.css b/src/css/nowplaying.css index 93765d541b..ab8695deed 100644 --- a/src/css/nowplaying.css +++ b/src/css/nowplaying.css @@ -186,14 +186,26 @@ } .nowPlayingVolumeSliderContainer { - width: 6em + width: 9em +} + +@media all and (max-width:50em) { + .nowPlayingInfoButtons .nowPlayingPageUserDataButtons { + display: none !important + } +} + +@media all and (max-width:47em) { + .nowPlayingInfoButtons .repeatToggleButton { + display: none !important + } } @media all and (max-width:34em) { - .btnNowPlayingFastForward, - .btnNowPlayingRewind, - .playlist .listItemMediaInfo { + .nowPlayingInfoButtons .btnNowPlayingFastForward, + .nowPlayingInfoButtons .btnNowPlayingRewind, + .nowPlayingInfoButtons .playlist .listItemMediaInfo { display: none !important } -} \ No newline at end of file +} diff --git a/src/css/videoosd.css b/src/css/videoosd.css index a8904b9945..bd24e41309 100644 --- a/src/css/videoosd.css +++ b/src/css/videoosd.css @@ -138,7 +138,7 @@ } .osdVolumeSliderContainer { - width: 6.5em; + width: 9em; -webkit-box-flex: 1; -webkit-flex-grow: 1; flex-grow: 1 @@ -244,14 +244,19 @@ } } -@media all and (max-width:37.5em) { +@media all and (max-width:43em) { .videoOsdBottom .volumeButtons { display: none !important } } +@media all and (max-width:50em) { + .videoOsdBottom .btnFastForward, .videoOsdBottom .btnRewind { + display: none !important + } +} @media all and (max-width:75em) { .videoOsdBottom .endsAtText { display: none !important } -} \ No newline at end of file +} From 44ba7a5cc4a42cb3f6877c65b223707837641d90 Mon Sep 17 00:00:00 2001 From: dkanada Date: Tue, 5 Mar 2019 21:12:13 +0900 Subject: [PATCH 045/220] deminification and move metadata path setting --- src/dashboard/dashboardgeneral.js | 45 ++++++++++++++++++++++++++----- src/dashboard/librarysettings.js | 17 +----------- src/dashboardgeneral.html | 13 ++++++++- src/librarysettings.html | 10 ------- 4 files changed, 51 insertions(+), 34 deletions(-) diff --git a/src/dashboard/dashboardgeneral.js b/src/dashboard/dashboardgeneral.js index f220be4cc0..74a7f1cc8f 100644 --- a/src/dashboard/dashboardgeneral.js +++ b/src/dashboard/dashboardgeneral.js @@ -12,13 +12,25 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb var form = this; $(form).parents(".page"); return ApiClient.getServerConfiguration().then(function(config) { - config.UICulture = $("#selectLocalizationLanguage", form).val(), config.CachePath = form.querySelector("#txtCachePath").value; - var requiresReload = !1; - config.UICulture !== currentLanguage && (requiresReload = !0), config.EnableAutomaticRestart = $("#chkEnableAutomaticRestart", form).checked(), config.EnableAutoUpdate = $("#chkEnableAutomaticServerUpdates", form).checked(), ApiClient.updateServerConfiguration(config).then(function() { + config.UICulture = $("#selectLocalizationLanguage", form).val(); + config.CachePath = form.querySelector("#txtCachePath").value; + var requiresReload = false; + if (config.UICulture !== currentLanguage) { + requiresReload = true; + } + config.EnableAutomaticRestart = $("#chkEnableAutomaticRestart", form).checked(); + config.EnableAutoUpdate = $("#chkEnableAutomaticServerUpdates", form).checked(); + ApiClient.updateServerConfiguration(config).then(function() { ApiClient.getNamedConfiguration(brandingConfigKey).then(function(brandingConfig) { - brandingConfig.LoginDisclaimer = form.querySelector("#txtLoginDisclaimer").value, brandingConfig.CustomCss = form.querySelector("#txtCustomCss").value, currentBrandingOptions && brandingConfig.CustomCss !== currentBrandingOptions.CustomCss && (requiresReload = !0), ApiClient.updateNamedConfiguration(brandingConfigKey, brandingConfig).then(function() { - Dashboard.processServerConfigurationUpdateResult(), requiresReload && !AppInfo.isNativeApp && window.location.reload(!0) - }) + brandingConfig.LoginDisclaimer = form.querySelector("#txtLoginDisclaimer").value; + brandingConfig.CustomCss = form.querySelector("#txtCustomCss").value; + currentBrandingOptions && brandingConfig.CustomCss !== currentBrandingOptions.CustomCss && (requiresReload = !0); + ApiClient.updateNamedConfiguration(brandingConfigKey, brandingConfig).then(function() { + Dashboard.processServerConfigurationUpdateResult(); + if (requiresReload && !AppInfo.isNativeApp) { + window.location.reload(true); + } + }); }) }) }), !1 @@ -37,7 +49,26 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb instruction: Globalize.translate("HeaderSelectServerCachePathHelp") }) }) - }), $(".dashboardGeneralForm", view).off("submit", onSubmit).on("submit", onSubmit), view.addEventListener("viewshow", function() { + }); + + $("#btnSelectMetadataPath", view).on("click.selectDirectory", function() { + require(["directorybrowser"], function(directoryBrowser) { + var picker = new directoryBrowser; + picker.show({ + path: $("#txtMetadataPath", view).val(), + networkSharePath: $("#txtMetadataNetworkPath", view).val(), + callback: function(path, networkPath) { + path && ($("#txtMetadataPath", view).val(path), $("#txtMetadataNetworkPath", view).val(networkPath)), picker.close() + }, + validateWriteable: !0, + header: Globalize.translate("HeaderSelectMetadataPath"), + instruction: Globalize.translate("HeaderSelectMetadataPathHelp"), + enableNetworkSharePath: !0 + }) + }) + }); + + $(".dashboardGeneralForm", view).off("submit", onSubmit).on("submit", onSubmit), view.addEventListener("viewshow", function() { var promise1 = ApiClient.getServerConfiguration(), promise2 = ApiClient.getJSON(ApiClient.getUrl("Localization/Options")), promise3 = ApiClient.getSystemInfo(); diff --git a/src/dashboard/librarysettings.js b/src/dashboard/librarysettings.js index afbf033dfb..4a967537b7 100644 --- a/src/dashboard/librarysettings.js +++ b/src/dashboard/librarysettings.js @@ -62,22 +62,7 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked", "emby-checkbox", "emby- }] } return function(view, params) { - $("#btnSelectMetadataPath", view).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; - picker.show({ - path: $("#txtMetadataPath", view).val(), - networkSharePath: $("#txtMetadataNetworkPath", view).val(), - callback: function(path, networkPath) { - path && ($("#txtMetadataPath", view).val(path), $("#txtMetadataNetworkPath", view).val(networkPath)), picker.close() - }, - validateWriteable: !0, - header: Globalize.translate("HeaderSelectMetadataPath"), - instruction: Globalize.translate("HeaderSelectMetadataPathHelp"), - enableNetworkSharePath: !0 - }) - }) - }), $(".librarySettingsForm").off("submit", onSubmit).on("submit", onSubmit), view.addEventListener("viewshow", function() { + $(".librarySettingsForm").off("submit", onSubmit).on("submit", onSubmit), view.addEventListener("viewshow", function() { libraryMenu.setTabs("librarysetup", 4, getTabs), loading.show(); var page = this; ApiClient.getServerConfiguration().then(function(config) { diff --git a/src/dashboardgeneral.html b/src/dashboardgeneral.html index 16d170e62b..a31db79d66 100644 --- a/src/dashboardgeneral.html +++ b/src/dashboardgeneral.html @@ -34,7 +34,7 @@
-

${Advanced}

+

${HeaderPaths}

@@ -44,6 +44,16 @@
${LabelCachePathHelp}
+
+
+
+ +
+ +
+
${LabelMetadataPathHelp}
+ +
@@ -62,6 +72,7 @@
+

${TabOther}

${LabelLoginDisclaimerHelp}
diff --git a/src/librarysettings.html b/src/librarysettings.html index 7b75ff7e19..f99ebfb4e0 100644 --- a/src/librarysettings.html +++ b/src/librarysettings.html @@ -11,16 +11,6 @@
${LabelDateAddedBehaviorHelp}
-
-
-
- -
- -
-
${LabelMetadataPathHelp}
- -
@@ -76,7 +74,6 @@
+
-

${HeaderPaths}

+
+

${HeaderPaths}

+ +
diff --git a/src/devices/devices.html b/src/devices/devices.html index f79d7954fd..6997f42eda 100644 --- a/src/devices/devices.html +++ b/src/devices/devices.html @@ -1,8 +1,6 @@
-
-

${TabDevices}

@@ -11,9 +9,6 @@
- - -
diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index 395834f9d8..c44eb9f6bf 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -189,7 +189,7 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " html += globalize.translate("HeaderAdmin"); html += ""; html += 'dashboard' + globalize.translate("TabDashboard") + ""; - html += 'mode_edit' + globalize.translate("MetadataManager") + ""; + html += 'mode_edit' + globalize.translate("Metadata") + ""; html += "
"; } diff --git a/src/scripts/plugincatalogpage.js b/src/scripts/plugincatalogpage.js index 40d57560b5..f18c56f2f0 100644 --- a/src/scripts/plugincatalogpage.js +++ b/src/scripts/plugincatalogpage.js @@ -41,82 +41,31 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-linkbutton", " if (!options.targetSystem || plugin.targetSystem == options.targetSystem) { return "UserInstalled" == plugin.type; } - - return false; } - return false; }); - availablePlugins = allPlugins.sort(function (a__e, b__r) { - var aName = a__e.category; - var bName = b__r.category; - if (aName > bName) { + availablePlugins = allPlugins.sort(function (a, b) { + if (a.category > b.category) { return 1; - } - - if (bName > aName) { + } else if (b.category > a.category) { return -1; } - - aName = a__e.name; - bName = b__r.name; - - if (aName > bName) { + if (a.name > b.name) { return 1; - } - - if (bName > aName) { + } else if (b.name > a.name) { return -1; } - return 0; }); + var i__q; var length; var plugin; var currentCategory; var html = ""; - if (!options.categories) { - currentCategory = globalize.translate("HeaderTopPlugins"); - html += '
'; - html += '

' + currentCategory + "

"; - var topPlugins = allPlugins.slice(0).sort(function (a__t, b__y) { - if (a__t.installs > b__y.installs) { - return -1; - } - - if (b__y.installs > a__t.installs) { - return 1; - } - - var aName = a__t.name; - var bName = b__y.name; - - if (aName > bName) { - return 1; - } - - if (bName > aName) { - return -1; - } - - return 0; - }); - html += '
'; - var limit = screen.availWidth >= 1920 ? 15 : 12; - - for (i__q = 0, length = Math.min(topPlugins.length, limit); i__q < length; i__q++) { - html += getPluginHtml(topPlugins[i__q], options, installedPlugins); - } - - html += "
"; - html += "
"; - } - var hasOpenTag = false; - for (currentCategory = null, false === options.showCategory && (html += '
', hasOpenTag = true), i__q = 0, length = availablePlugins.length; i__q < length; i__q++) { plugin = availablePlugins[i__q]; var category = plugin.categoryDisplayName; From 07673d0ae6a06b86ca4a0319c8292a9c03e161dd Mon Sep 17 00:00:00 2001 From: dkanada Date: Wed, 6 Mar 2019 16:43:39 +0900 Subject: [PATCH 053/220] remove a dead setting from dlna page --- src/dlnasettings.html | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/dlnasettings.html b/src/dlnasettings.html index a3cb1f10fa..5eb5cd452d 100644 --- a/src/dlnasettings.html +++ b/src/dlnasettings.html @@ -10,11 +10,6 @@

${TabSettings}

${Help}
- -
- -
${LabelRemoteClientBitrateLimitHelp}
-
From 579fbe90c8544f0e22fe11876d4d3cd8cfc4b566 Mon Sep 17 00:00:00 2001 From: dkanada Date: Wed, 6 Mar 2019 17:53:44 +0900 Subject: [PATCH 054/220] remove appservices page in favor of plugin catalog --- src/appservices.html | 21 ----------- src/dashboard/livetvtuner.js | 10 ------ src/livetvstatus.html | 8 ++--- src/livetvtuner.html | 7 ++-- src/notificationsettings.html | 6 +--- src/scripts/appservices.js | 56 ----------------------------- src/scripts/livetvstatus.js | 10 ------ src/scripts/notificationsettings.js | 9 ----- src/scripts/site.js | 5 --- 9 files changed, 7 insertions(+), 125 deletions(-) delete mode 100644 src/appservices.html delete mode 100644 src/scripts/appservices.js diff --git a/src/appservices.html b/src/appservices.html deleted file mode 100644 index 43f37a0980..0000000000 --- a/src/appservices.html +++ /dev/null @@ -1,21 +0,0 @@ -
- -
-
- -
- -
-

${HeaderInstalledServices}

- ${Help} -
- -
-
-
-

${HeaderAvailableServices}

-
-
-
-
-
\ No newline at end of file diff --git a/src/dashboard/livetvtuner.js b/src/dashboard/livetvtuner.js index b32e01b2d2..5ded7e6bf4 100644 --- a/src/dashboard/livetvtuner.js +++ b/src/dashboard/livetvtuner.js @@ -74,16 +74,6 @@ define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button }) } - function getTabs() { - return [{ - href: "livetvstatus.html", - name: globalize.translate("TabDevices") - }, { - href: "appservices.html?context=livetv", - name: globalize.translate("TabServices") - }] - } - function onTypeChange() { var value = this.value, view = dom.parentWithClass(this, "page"), diff --git a/src/livetvstatus.html b/src/livetvstatus.html index 281c1e7a97..f6a0c8aeb2 100644 --- a/src/livetvstatus.html +++ b/src/livetvstatus.html @@ -1,11 +1,7 @@ -
- +
- -
-

@@ -31,8 +27,8 @@
-
+
diff --git a/src/livetvtuner.html b/src/livetvtuner.html index 47fd5e2b26..71ddde77d7 100644 --- a/src/livetvtuner.html +++ b/src/livetvtuner.html @@ -1,8 +1,6 @@ -
- +
-
@@ -47,6 +45,7 @@
${ImportFavoriteChannelsHelp}
+
${AllowHWTranscodingHelp}
+
${EnableStreamLoopingHelp}
+

${DrmChannelsNotImported}

${ForAdditionalLiveTvOptions}


diff --git a/src/notificationsettings.html b/src/notificationsettings.html index 279e1bc565..e0747c34b3 100644 --- a/src/notificationsettings.html +++ b/src/notificationsettings.html @@ -1,13 +1,9 @@ -
- +
-
-
-
diff --git a/src/scripts/appservices.js b/src/scripts/appservices.js deleted file mode 100644 index 03ec8225bf..0000000000 --- a/src/scripts/appservices.js +++ /dev/null @@ -1,56 +0,0 @@ -define(["loading", "libraryMenu"], function(loading, libraryMenu) { - "use strict"; - - function reloadList(page) { - loading.show(); - var promise1 = ApiClient.getAvailablePlugins({ - TargetSystems: "Server" - }), - promise2 = ApiClient.getInstalledPlugins(); - Promise.all([promise1, promise2]).then(function(responses) { - renderInstalled(page, responses[0], responses[1]), renderCatalog(page, responses[0], responses[1]) - }) - } - - function getCategories() { - var context = getParameterByName("context"), - categories = []; - return "sync" == context ? categories.push("Sync") : "livetv" == context ? categories.push("Live TV") : "notifications" == context && categories.push("Notifications"), categories - } - - function renderInstalled(page, availablePlugins, installedPlugins) { - requirejs(["scripts/pluginspage"], function() { - var category = getCategories()[0]; - installedPlugins = installedPlugins.filter(function(i) { - var catalogEntry = availablePlugins.filter(function(a) { - return (a.guid || "").toLowerCase() == (i.Id || "").toLowerCase() - })[0]; - return !!catalogEntry && catalogEntry.category == category - }), PluginsPage.renderPlugins(page, installedPlugins) - }) - } - - function renderCatalog(page, availablePlugins, installedPlugins) { - requirejs(["scripts/plugincatalogpage"], function() { - var categories = getCategories(); - PluginCatalog.renderCatalog({ - catalogElement: page.querySelector(".catalog"), - availablePlugins: availablePlugins, - installedPlugins: installedPlugins, - categories: categories, - showCategory: !1, - context: getParameterByName("context"), - targetSystem: "Server" - }) - }) - } - - function onPageShow() { - var page = this, - context = getParameterByName("context"); - "sync" == context ? (libraryMenu.setTitle(Globalize.translate("TitleSync")), page.querySelector(".headerHelpButton").setAttribute("href", "https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Sync")) : "livetv" == context ? (libraryMenu.setTitle(Globalize.translate("TitleLiveTV")), page.querySelector(".headerHelpButton").setAttribute("href", "https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Live-TV")) : "notifications" == context && (libraryMenu.setTitle(Globalize.translate("TitleNotifications")), page.querySelector(".headerHelpButton").setAttribute("href", "https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Notifications")) - } - pageIdOn("pagebeforeshow", "appServicesPage", onPageShow), pageIdOn("pageshow", "appServicesPage", onPageShow), pageIdOn("pageshow", "appServicesPage", function() { - reloadList(this) - }) -}); \ No newline at end of file diff --git a/src/scripts/livetvstatus.js b/src/scripts/livetvstatus.js index 96f7b3dd91..1beb1a9c69 100644 --- a/src/scripts/livetvstatus.js +++ b/src/scripts/livetvstatus.js @@ -188,16 +188,6 @@ define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layo Dashboard.navigate("livetvtuner.html") } - function getTabs() { - return [{ - href: "livetvstatus.html", - name: globalize.translate("TabDevices") - }, { - href: "appservices.html?context=livetv", - name: globalize.translate("TabServices") - }] - } - function showDeviceMenu(button, tunerDeviceId) { var items = []; items.push({ diff --git a/src/scripts/notificationsettings.js b/src/scripts/notificationsettings.js index b0c8bfe573..173db03bca 100644 --- a/src/scripts/notificationsettings.js +++ b/src/scripts/notificationsettings.js @@ -13,15 +13,6 @@ define(["loading", "libraryMenu", "globalize", "listViewStyle", "emby-linkbutton }) } - function getTabs() { - return [{ - href: "notificationsettings.html", - name: globalize.translate("TabNotifications") - }, { - href: "appservices.html?context=notifications", - name: globalize.translate("TabServices") - }] - } return function(view, params) { view.addEventListener("viewshow", function() { libraryMenu.setTabs("notifications", 0, getTabs), reload(view) diff --git a/src/scripts/site.js b/src/scripts/site.js index 2d6c15b1eb..c012caba9e 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -423,11 +423,6 @@ var Dashboard = { autoFocus: !1, roles: "admin", controller: "scripts/addpluginpage" - }), defineRoute({ - path: "/appservices.html", - dependencies: [], - autoFocus: !1, - roles: "admin" }), defineRoute({ path: "/autoorganizelog.html", dependencies: [], From 74eabd2af96eba08f946b72bb0a478829dc45238 Mon Sep 17 00:00:00 2001 From: dkanada Date: Wed, 6 Mar 2019 18:18:49 +0900 Subject: [PATCH 055/220] fix js crash from missing method and deminification --- src/dashboard/livetvtuner.js | 52 ++++++++++++++++++++--------- src/scripts/livetvstatus.js | 1 - src/scripts/notificationsettings.js | 51 +++++++++++++++++++++++----- 3 files changed, 80 insertions(+), 24 deletions(-) diff --git a/src/dashboard/livetvtuner.js b/src/dashboard/livetvtuner.js index 5ded7e6bf4..1cc806d05b 100644 --- a/src/dashboard/livetvtuner.js +++ b/src/dashboard/livetvtuner.js @@ -2,31 +2,54 @@ define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button "use strict"; function isM3uVariant(type) { - return -1 !== ["nextpvr"].indexOf(type || "") + return ["nextpvr"].indexOf(type || "") !== -1; } function fillTypes(view, currentId) { - return ApiClient.getJSON(ApiClient.getUrl("LiveTv/TunerHosts/Types")).then(function(types) { + ApiClient.getJSON(ApiClient.getUrl("LiveTv/TunerHosts/Types")).then(function(types) { var selectType = view.querySelector(".selectType"); selectType.innerHTML = types.map(function(t) { - return '" - }).join("") + '", selectType.disabled = null != currentId, selectType.value = "", onTypeChange.call(selectType) - }) + return '"; + }).join(""); + selectType.innerHTML += '"; + + selectType.disabled = null != currentId; + selectType.value = ""; + onTypeChange.call(selectType); + }); } function reload(view, providerId) { - view.querySelector(".txtDevicePath").value = "", view.querySelector(".chkFavorite").checked = !1, view.querySelector(".txtDevicePath").value = "", providerId && ApiClient.getNamedConfiguration("livetv").then(function(config) { - var info = config.TunerHosts.filter(function(i) { - return i.Id === providerId - })[0]; - fillTunerHostInfo(view, info) - }) + view.querySelector(".txtDevicePath").value = ""; + view.querySelector(".chkFavorite").checked = false; + view.querySelector(".txtDevicePath").value = ""; + if (providerId) { + ApiClient.getNamedConfiguration("livetv").then(function(config) { + var info = config.TunerHosts.filter(function(i) { + return i.Id === providerId; + })[0]; + fillTunerHostInfo(view, info); + }); + } } function fillTunerHostInfo(view, info) { - var selectType = view.querySelector(".selectType"), - type = info.Type || ""; - info.Source && isM3uVariant(info.Source) && (type = info.Source), selectType.value = type, onTypeChange.call(selectType), view.querySelector(".txtDevicePath").value = info.Url || "", view.querySelector(".txtFriendlyName").value = info.FriendlyName || "", view.querySelector(".txtUserAgent").value = info.UserAgent || "", view.querySelector(".fldDeviceId").value = info.DeviceId || "", view.querySelector(".chkFavorite").checked = info.ImportFavoritesOnly, view.querySelector(".chkTranscode").checked = info.AllowHWTranscoding, view.querySelector(".chkStreamLoop").checked = info.EnableStreamLooping, view.querySelector(".txtTunerCount").value = info.TunerCount || "0" + var selectType = view.querySelector(".selectType"); + var type = info.Type || ""; + if (info.Source && isM3uVariant(info.Source)) { + selectType.value = info.Source; + onTypeChange.call(selectType); + } + view.querySelector(".txtDevicePath").value = info.Url || ""; + view.querySelector(".txtFriendlyName").value = info.FriendlyName || ""; + view.querySelector(".txtUserAgent").value = info.UserAgent || ""; + view.querySelector(".fldDeviceId").value = info.DeviceId || ""; + view.querySelector(".chkFavorite").checked = info.ImportFavoritesOnly; + view.querySelector(".chkTranscode").checked = info.AllowHWTranscoding; + view.querySelector(".chkStreamLoop").checked = info.EnableStreamLooping; + view.querySelector(".txtTunerCount").value = info.TunerCount || "0"; } function submitForm(page) { @@ -92,7 +115,6 @@ define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button } return function(view, params) { params.id || view.querySelector(".btnDetect").classList.remove("hide"), view.addEventListener("viewshow", function() { - libraryMenu.setTabs("livetvadmin", 0, getTabs); var currentId = params.id; fillTypes(view, currentId).then(function() { reload(view, currentId) diff --git a/src/scripts/livetvstatus.js b/src/scripts/livetvstatus.js index 1beb1a9c69..3a7078ccd8 100644 --- a/src/scripts/livetvstatus.js +++ b/src/scripts/livetvstatus.js @@ -230,7 +230,6 @@ define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layo addProvider(this) }), page.querySelector(".devicesList").addEventListener("click", onDevicesListClick) }).on("pageshow", "#liveTvStatusPage", function() { - libraryMenu.setTabs("livetvadmin", 0, getTabs); var page = this; reload(page), taskButton({ mode: "on", diff --git a/src/scripts/notificationsettings.js b/src/scripts/notificationsettings.js index 173db03bca..78948fd56b 100644 --- a/src/scripts/notificationsettings.js +++ b/src/scripts/notificationsettings.js @@ -2,20 +2,55 @@ define(["loading", "libraryMenu", "globalize", "listViewStyle", "emby-linkbutton "use strict"; function reload(page) { - loading.show(), ApiClient.getJSON(ApiClient.getUrl("Notifications/Types")).then(function(list) { - var html = "", - lastCategory = "", - showHelp = !0; + loading.show(); + ApiClient.getJSON(ApiClient.getUrl("Notifications/Types")).then(function(list) { + var html = ""; + var lastCategory = ""; + var showHelp = true; html += list.map(function(i) { var itemHtml = ""; - return i.Category != lastCategory && (lastCategory = i.Category, lastCategory && (itemHtml += "
", itemHtml += "
"), itemHtml += '
', itemHtml += '
', itemHtml += '

', itemHtml += i.Category, itemHtml += "

", showHelp && (showHelp = !1, itemHtml += '' + globalize.translate("Help") + ""), itemHtml += "
", itemHtml += '", html += "
"), page.querySelector(".notificationList").innerHTML = html, loading.hide() + if (i.Category !== lastCategory) { + lastCategory = i.Category; + if (lastCategory) { + itemHtml += "
"; + itemHtml += "
"; + } + itemHtml += '
'; + itemHtml += '
'; + itemHtml += '

'; + itemHtml += i.Category; + itemHtml += "

"; + if (showHelp) { + showHelp = false; + itemHtml += ''; + itemHtml += globalize.translate("Help"); + itemHtml += ""; + } + itemHtml += "
"; + itemHtml += '"; + html += "
"; + } + page.querySelector(".notificationList").innerHTML = html; + loading.hide(); }) } return function(view, params) { view.addEventListener("viewshow", function() { - libraryMenu.setTabs("notifications", 0, getTabs), reload(view) - }) + reload(view); + }); } }); \ No newline at end of file From f3e07e153159bd8115974dd5e9daac1adfe5ec90 Mon Sep 17 00:00:00 2001 From: dkanada Date: Wed, 6 Mar 2019 18:53:31 +0900 Subject: [PATCH 056/220] move network share path out of directory browser component --- .../directorybrowser/directorybrowser.js | 34 +++++-------------- src/dashboard/dashboardgeneral.js | 23 ++++++++++--- src/dashboardgeneral.html | 14 ++++++-- 3 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/components/directorybrowser/directorybrowser.js b/src/components/directorybrowser/directorybrowser.js index 7eb91fffa0..592885721b 100644 --- a/src/components/directorybrowser/directorybrowser.js +++ b/src/components/directorybrowser/directorybrowser.js @@ -18,18 +18,18 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'emby-b if (path && typeof path !== 'string') { throw new Error("invalid path"); } - + loading.show(); - + var promises = []; if ("Network" === path) { promises.push(ApiClient.getNetworkDevices()) } else { - if (path) { + if (path) { promises.push(ApiClient.getDirectoryContents(path, fileOptions)); promises.push(ApiClient.getParentPath(path)); - } else { + } else { promises.push(ApiClient.getDrives()); } } @@ -42,7 +42,7 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'emby-b page.querySelector(".results").scrollTop = 0; page.querySelector("#txtDirectoryPickerPath").value = path || ""; - + if (path) { html += getItem("lnkPath lnkDirectory", "", parentPath, "..."); } @@ -51,7 +51,7 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'emby-b var cssClass = "File" === folder.Type ? "lnkPath lnkFile" : "lnkPath lnkDirectory"; html += getItem(cssClass, folder.Type, folder.Path, folder.Name); } - + if (!path) { html += getItem("lnkPath lnkDirectory", "", "Network", Globalize.translate("ButtonNetwork")); } @@ -128,17 +128,9 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'emby-b html += ''; } html += "
"; - if (!readOnlyAttribute) { + if (!readOnlyAttribute) { html += '
'; } - if (options.enableNetworkSharePath) { - html += '
'; - html += ''; - html += '
'; - html += Globalize.translate("LabelOptionalNetworkPathHelp"); - html += "
"; - html += "
"; - } html += '
'; html += '"; html += "
"; @@ -219,14 +211,8 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'emby-b content.querySelector("form").addEventListener("submit", function(e) { if (options.callback) { - var networkSharePath = this.querySelector("#txtNetworkPath"); - networkSharePath = networkSharePath ? networkSharePath.value : null; var path = this.querySelector("#txtDirectoryPickerPath").value; - validatePath(path, options.validateWriteable, ApiClient).then( - function() { - options.callback(path, networkSharePath); - } - ); + validatePath(path, options.validateWriteable, ApiClient).then(options.callback(path)); } e.preventDefault(); e.stopPropagation(); @@ -293,10 +279,6 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'emby-b }); currentDialog = dlg; dlg.querySelector("#txtDirectoryPickerPath").value = initialPath; - var txtNetworkPath = dlg.querySelector("#txtNetworkPath"); - if (txtNetworkPath) { - txtNetworkPath.value = options.networkSharePath || ""; - } if (!options.pathReadOnly) { refreshDirectoryBrowser(dlg, initialPath, fileOptions, true); } diff --git a/src/dashboard/dashboardgeneral.js b/src/dashboard/dashboardgeneral.js index 760ae087a0..027fba9991 100644 --- a/src/dashboard/dashboardgeneral.js +++ b/src/dashboard/dashboardgeneral.js @@ -74,16 +74,29 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb var picker = new directoryBrowser; picker.show({ path: $("#txtMetadataPath", view).val(), - networkSharePath: $("#txtMetadataNetworkPath", view).val(), - callback: function(path, networkPath) { + callback: function(path) { path && $("#txtMetadataPath", view).val(path); - networkPath && $("#txtMetadataNetworkPath", view).val(networkPath); picker.close(); }, validateWriteable: true, header: Globalize.translate("HeaderSelectMetadataPath"), - instruction: Globalize.translate("HeaderSelectMetadataPathHelp"), - enableNetworkSharePath: true + instruction: Globalize.translate("HeaderSelectMetadataPathHelp") + }) + }) + }); + + $("#btnSelectMetadataNetworkPath", view).on("click.selectDirectory", function() { + require(["directorybrowser"], function(directoryBrowser) { + var picker = new directoryBrowser; + picker.show({ + path: $("#txtMetadataNetworkPath", view).val(), + callback: function(path) { + path && $("#txtMetadataNetworkPath", view).val(path); + picker.close(); + }, + validateWriteable: true, + header: Globalize.translate("LabelOptionalNetworkPath"), + instruction: Globalize.translate("LabelOptionalNetworkPathHelp") }) }) }); diff --git a/src/dashboardgeneral.html b/src/dashboardgeneral.html index a31db79d66..4c56fa300b 100644 --- a/src/dashboardgeneral.html +++ b/src/dashboardgeneral.html @@ -44,6 +44,7 @@
${LabelCachePathHelp}
+
@@ -52,7 +53,16 @@
${LabelMetadataPathHelp}
- +
+ +
+
+
+ +
+ +
+
${LabelOptionalNetworkPathHelp}
@@ -72,7 +82,7 @@
-

${TabOther}

+

${HeaderBranding}

${LabelLoginDisclaimerHelp}
From 14005d6c6397c8d42b839ffce54e3261c9bed04d Mon Sep 17 00:00:00 2001 From: dkanada Date: Wed, 6 Mar 2019 19:13:44 +0900 Subject: [PATCH 057/220] comment out multiserver and add check in navigation drawer --- src/components/apphost.js | 2 +- src/scripts/librarymenu.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/apphost.js b/src/components/apphost.js index 8de18f166f..619cd298b7 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -143,7 +143,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function(appSett features.push("displaylanguage"); features.push("otherapppromotions"); features.push("targetblank"); - features.push("multiserver"); + //features.push("multiserver"); browser.orsay || browser.tizen || browser.msie || !(browser.firefox || browser.ps4 || browser.edge || cueSupported()) || features.push("subtitleappearancesettings"); browser.orsay || browser.tizen || features.push("subtitleburnsettings"); browser.tv || browser.ps4 || browser.xboxOne || features.push("fileinput"); diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index c44eb9f6bf..a637a779c4 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -199,7 +199,9 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " html += "

"; if (user.localUser) { html += 'settings' + globalize.translate("ButtonSettings") + ""; - html += 'wifi' + globalize.translate("ButtonSelectServer") + ""; + if (appHost.supports("multiserver")) { + html += 'wifi' + globalize.translate("ButtonSelectServer") + ""; + } if (!user.localUser.EnableAutoLogin) { html += 'exit_to_app' + globalize.translate("ButtonSignOut") + ""; } From 62bb9f8721965aa401d62fb3e9bfc10c9e675003 Mon Sep 17 00:00:00 2001 From: Vasily Date: Thu, 7 Mar 2019 21:19:21 +0000 Subject: [PATCH 058/220] Update src/scripts/encodingsettings.js Co-Authored-By: ploughpuff <33969763+ploughpuff@users.noreply.github.com> --- src/scripts/encodingsettings.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/scripts/encodingsettings.js b/src/scripts/encodingsettings.js index 88e08f87d3..20f42e4f26 100644 --- a/src/scripts/encodingsettings.js +++ b/src/scripts/encodingsettings.js @@ -4,7 +4,18 @@ define(["jQuery", "loading", "globalize", "dom"], function($, loading, globalize function loadPage(page, config, systemInfo) { Array.prototype.forEach.call(page.querySelectorAll(".chkDecodeCodec"), function(c) { c.checked = -1 !== (config.HardwareDecodingCodecs || []).indexOf(c.getAttribute("data-codec")) - }), page.querySelector("#chkHardwareEncoding").checked = config.EnableHardwareEncoding, $("#selectVideoDecoder", page).val(config.HardwareAccelerationType), $("#selectThreadCount", page).val(config.EncodingThreadCount), $("#txtDownMixAudioBoost", page).val(config.DownMixAudioBoost), page.querySelector(".txtEncoderPath").value = config.EncoderAppPathDisplay || "", $("#txtTranscodingTempPath", page).val(config.TranscodingTempPath || ""), $("#txtVaapiDevice", page).val(config.VaapiDevice || ""), page.querySelector("#selectH264Preset").value = config.H264Preset || "", page.querySelector("#txtH264Crf").value = config.H264Crf || "", page.querySelector("#chkEnableSubtitleExtraction").checked = config.EnableSubtitleExtraction || !1, page.querySelector("#selectVideoDecoder").dispatchEvent(new CustomEvent("change", { + }); + page.querySelector("#chkHardwareEncoding").checked = config.EnableHardwareEncoding; + $("#selectVideoDecoder", page).val(config.HardwareAccelerationType); + $("#selectThreadCount", page).val(config.EncodingThreadCount); + $("#txtDownMixAudioBoost", page).val(config.DownMixAudioBoost); + page.querySelector(".txtEncoderPath").value = config.EncoderAppPathDisplay || ""; + $("#txtTranscodingTempPath", page).val(config.TranscodingTempPath || ""); + $("#txtVaapiDevice", page).val(config.VaapiDevice || ""); + page.querySelector("#selectH264Preset").value = config.H264Preset || ""; + page.querySelector("#txtH264Crf").value = config.H264Crf || ""; + page.querySelector("#chkEnableSubtitleExtraction").checked = config.EnableSubtitleExtraction || false; + page.querySelector("#selectVideoDecoder").dispatchEvent(new CustomEvent("change", { bubbles: !0 })), loading.hide() } From 06d215443473cdec90165fe729721baed9b17ba5 Mon Sep 17 00:00:00 2001 From: Vasily Date: Thu, 7 Mar 2019 22:00:13 +0000 Subject: [PATCH 059/220] apply suggestions from code review Co-Authored-By: dkanada --- src/dashboard/dashboardgeneral.js | 52 +++++++++++++++++++++-------- src/dashboard/librarysettings.js | 6 +++- src/scripts/notificationsettings.js | 8 +++-- 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/dashboard/dashboardgeneral.js b/src/dashboard/dashboardgeneral.js index 027fba9991..cf9d58f3dd 100644 --- a/src/dashboard/dashboardgeneral.js +++ b/src/dashboard/dashboardgeneral.js @@ -2,7 +2,11 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb "use strict"; function loadPage(page, config, languageOptions, systemInfo) { - systemInfo.CanLaunchWebBrowser ? page.querySelector("#fldRunWebAppAtStartup").classList.remove("hide") : page.querySelector("#fldRunWebAppAtStartup").classList.add("hide"); + if (systemInfo.CanLaunchWebBrowser) { + page.querySelector("#fldRunWebAppAtStartup").classList.remove("hide"); + } else { + page.querySelector("#fldRunWebAppAtStartup").classList.add("hide"); + } page.querySelector("#txtCachePath").value = config.CachePath || ""; $("#txtMetadataPath", page).val(config.MetadataPath || ""); $("#txtMetadataNetworkPath", page).val(config.MetadataNetworkPath || ""); @@ -10,11 +14,23 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb return '" })).val(config.UICulture); currentLanguage = config.UICulture; - systemInfo.CanSelfUpdate ? page.querySelector(".fldAutomaticUpdates").classList.remove("hide") : page.querySelector(".fldAutomaticUpdates").classList.add("hide"); + if (systemInfo.CanSelfUpdate) { + page.querySelector(".fldAutomaticUpdates").classList.remove("hide"); + } else { + page.querySelector(".fldAutomaticUpdates").classList.add("hide"); + } $("#chkEnableAutomaticServerUpdates", page).checked(config.EnableAutoUpdate); $("#chkEnableAutomaticRestart", page).checked(config.EnableAutomaticRestart); - systemInfo.CanSelfRestart ? page.querySelector("#fldEnableAutomaticRestart").classList.remove("hide") : page.querySelector("#fldEnableAutomaticRestart").classList.add("hide"); - systemInfo.CanSelfRestart || systemInfo.CanSelfUpdate ? $(".autoUpdatesContainer", page).removeClass("hide") : $(".autoUpdatesContainer", page).addClass("hide"); + if (systemInfo.CanSelfRestart) { + page.querySelector("#fldEnableAutomaticRestart").classList.remove("hide"); + } else { + page.querySelector("#fldEnableAutomaticRestart").classList.add("hide"); + } + if (systemInfo.CanSelfRestart || systemInfo.CanSelfUpdate) { + $(".autoUpdatesContainer", page).removeClass("hide"); + } else { + $(".autoUpdatesContainer", page).addClass("hide"); + } loading.hide(); } @@ -37,7 +53,9 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb ApiClient.getNamedConfiguration(brandingConfigKey).then(function(brandingConfig) { brandingConfig.LoginDisclaimer = form.querySelector("#txtLoginDisclaimer").value; brandingConfig.CustomCss = form.querySelector("#txtCustomCss").value; - currentBrandingOptions && brandingConfig.CustomCss !== currentBrandingOptions.CustomCss && (requiresReload = !0); + if (currentBrandingOptions && brandingConfig.CustomCss !== currentBrandingOptions.CustomCss) { + requiresReload = true; + } ApiClient.updateNamedConfiguration(brandingConfigKey, brandingConfig).then(function() { Dashboard.processServerConfigurationUpdateResult(); if (requiresReload && !AppInfo.isNativeApp) { @@ -59,7 +77,9 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb var picker = new directoryBrowser; picker.show({ callback: function(path) { - path && (view.querySelector("#txtCachePath").value = path); + if (path) { + view.querySelector("#txtCachePath").value = path; + } picker.close(); }, validateWriteable: true, @@ -71,11 +91,13 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb $("#btnSelectMetadataPath", view).on("click.selectDirectory", function() { require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + var picker = new directoryBrowser(); picker.show({ path: $("#txtMetadataPath", view).val(), callback: function(path) { - path && $("#txtMetadataPath", view).val(path); + if (path) { + $("#txtMetadataPath", view).val(path); + } picker.close(); }, validateWriteable: true, @@ -87,11 +109,13 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb $("#btnSelectMetadataNetworkPath", view).on("click.selectDirectory", function() { require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + var picker = new directoryBrowser(); picker.show({ path: $("#txtMetadataNetworkPath", view).val(), callback: function(path) { - path && $("#txtMetadataNetworkPath", view).val(path); + if (path) { + $("#txtMetadataNetworkPath", view).val(path); + } picker.close(); }, validateWriteable: true, @@ -103,10 +127,10 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb $(".dashboardGeneralForm", view).off("submit", onSubmit).on("submit", onSubmit); view.addEventListener("viewshow", function() { - var promise1 = ApiClient.getServerConfiguration(); - var promise2 = ApiClient.getJSON(ApiClient.getUrl("Localization/Options")); - var promise3 = ApiClient.getSystemInfo(); - Promise.all([promise1, promise2, promise3]).then(function(responses) { + var promiseConfig = ApiClient.getServerConfiguration(); + var promiseLanguageOptions = ApiClient.getJSON(ApiClient.getUrl("Localization/Options")); + var promiseSystemInfo = ApiClient.getSystemInfo(); + Promise.all([promiseConfig, promiseLanguageOptions, promiseSystemInfo]).then(function(responses) { loadPage(view, responses[0], responses[1], responses[2]); }); ApiClient.getNamedConfiguration(brandingConfigKey).then(function(config) { diff --git a/src/dashboard/librarysettings.js b/src/dashboard/librarysettings.js index e044a68cb6..5e700b6fb0 100644 --- a/src/dashboard/librarysettings.js +++ b/src/dashboard/librarysettings.js @@ -80,7 +80,11 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked", "emby-checkbox", "emby- loadFanartConfig(page, metadata) }); ApiClient.getSystemInfo().then(function(info) { - "Windows" === info.OperatingSystem ? page.querySelector(".fldSaveMetadataHidden").classList.remove("hide") : page.querySelector(".fldSaveMetadataHidden").classList.add("hide") + if ("Windows" === info.OperatingSystem) { + page.querySelector(".fldSaveMetadataHidden").classList.remove("hide"); + } else { + page.querySelector(".fldSaveMetadataHidden").classList.add("hide"); + } }); }); } diff --git a/src/scripts/notificationsettings.js b/src/scripts/notificationsettings.js index 78948fd56b..317abce620 100644 --- a/src/scripts/notificationsettings.js +++ b/src/scripts/notificationsettings.js @@ -30,7 +30,11 @@ define(["loading", "libraryMenu", "globalize", "listViewStyle", "emby-linkbutton itemHtml += '
'; } itemHtml += ''; - i.Enabled ? itemHtml += 'notifications_active' : itemHtml += 'notifications_off'; + if (i.Enabled) { + itemHtml += 'notifications_active'; + } else { + itemHtml += 'notifications_off'; + } itemHtml += '
'; itemHtml += '
' + i.Name + "
"; itemHtml += "
"; @@ -53,4 +57,4 @@ define(["loading", "libraryMenu", "globalize", "listViewStyle", "emby-linkbutton reload(view); }); } -}); \ No newline at end of file +}); From b9d21084f076f3ee3bbf580b2befe295bbc59854 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Fri, 8 Mar 2019 09:15:12 +0000 Subject: [PATCH 060/220] Update src/scripts/encodingsettings.js Co-Authored-By: ploughpuff <33969763+ploughpuff@users.noreply.github.com> --- src/scripts/encodingsettings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/encodingsettings.js b/src/scripts/encodingsettings.js index 20f42e4f26..f02e4d488a 100644 --- a/src/scripts/encodingsettings.js +++ b/src/scripts/encodingsettings.js @@ -101,7 +101,7 @@ define(["jQuery", "loading", "globalize", "dom"], function($, loading, globalize var page = this; ApiClient.getNamedConfiguration("encoding").then(function(config) { ApiClient.getSystemInfo().then(function(systemInfo) { - loadPage(page, config, systemInfo) + loadPage(page, config, systemInfo); }) }) }) From 36a0df3c7d4398988378d961fb046fafc1a7a247 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Fri, 8 Mar 2019 09:15:19 +0000 Subject: [PATCH 061/220] Update src/scripts/encodingsettings.js Co-Authored-By: ploughpuff <33969763+ploughpuff@users.noreply.github.com> --- src/scripts/encodingsettings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/encodingsettings.js b/src/scripts/encodingsettings.js index f02e4d488a..5ac984161b 100644 --- a/src/scripts/encodingsettings.js +++ b/src/scripts/encodingsettings.js @@ -16,7 +16,7 @@ define(["jQuery", "loading", "globalize", "dom"], function($, loading, globalize page.querySelector("#txtH264Crf").value = config.H264Crf || ""; page.querySelector("#chkEnableSubtitleExtraction").checked = config.EnableSubtitleExtraction || false; page.querySelector("#selectVideoDecoder").dispatchEvent(new CustomEvent("change", { - bubbles: !0 + bubbles: true })), loading.hide() } From 6565ec4009476f33bce4d93f3d415d77b9581c09 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Fri, 8 Mar 2019 09:25:45 +0000 Subject: [PATCH 062/220] Update src/scripts/encodingsettings.js Co-Authored-By: ploughpuff <33969763+ploughpuff@users.noreply.github.com> --- src/scripts/encodingsettings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/encodingsettings.js b/src/scripts/encodingsettings.js index 5ac984161b..13b48151b8 100644 --- a/src/scripts/encodingsettings.js +++ b/src/scripts/encodingsettings.js @@ -16,7 +16,7 @@ define(["jQuery", "loading", "globalize", "dom"], function($, loading, globalize page.querySelector("#txtH264Crf").value = config.H264Crf || ""; page.querySelector("#chkEnableSubtitleExtraction").checked = config.EnableSubtitleExtraction || false; page.querySelector("#selectVideoDecoder").dispatchEvent(new CustomEvent("change", { - bubbles: true + bubbles: true })), loading.hide() } From 90290d30dba221d27757ca8d7ced8617c448561f Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 9 Mar 2019 11:37:40 +0900 Subject: [PATCH 063/220] fix some other code clarity issues --- src/components/apphost.js | 1 + src/dashboard/dashboardgeneral.js | 9 +++------ src/dashboard/livetvtuner.js | 17 ++++++++++------- src/scripts/notificationsettings.js | 14 +++++++------- src/scripts/plugincatalogpage.js | 13 +++++++------ 5 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/components/apphost.js b/src/components/apphost.js index 619cd298b7..9cffd2d8a4 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -143,6 +143,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function(appSett features.push("displaylanguage"); features.push("otherapppromotions"); features.push("targetblank"); + // allows users to connect to more than one server //features.push("multiserver"); browser.orsay || browser.tizen || browser.msie || !(browser.firefox || browser.ps4 || browser.edge || cueSupported()) || features.push("subtitleappearancesettings"); browser.orsay || browser.tizen || features.push("subtitleburnsettings"); diff --git a/src/dashboard/dashboardgeneral.js b/src/dashboard/dashboardgeneral.js index cf9d58f3dd..c2f48a2803 100644 --- a/src/dashboard/dashboardgeneral.js +++ b/src/dashboard/dashboardgeneral.js @@ -10,8 +10,8 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb page.querySelector("#txtCachePath").value = config.CachePath || ""; $("#txtMetadataPath", page).val(config.MetadataPath || ""); $("#txtMetadataNetworkPath", page).val(config.MetadataNetworkPath || ""); - $("#selectLocalizationLanguage", page).html(languageOptions.map(function(l) { - return '" + $("#selectLocalizationLanguage", page).html(languageOptions.map(function(language) { + return '" })).val(config.UICulture); currentLanguage = config.UICulture; if (systemInfo.CanSelfUpdate) { @@ -43,10 +43,7 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb config.CachePath = form.querySelector("#txtCachePath").value; config.MetadataPath = $("#txtMetadataPath", form).val(); config.MetadataNetworkPath = $("#txtMetadataNetworkPath", form).val(); - var requiresReload = false; - if (config.UICulture !== currentLanguage) { - requiresReload = true; - } + var requiresReload = (config.UICulture !== currentLanguage); config.EnableAutomaticRestart = $("#chkEnableAutomaticRestart", form).checked(); config.EnableAutoUpdate = $("#chkEnableAutomaticServerUpdates", form).checked(); ApiClient.updateServerConfiguration(config).then(function() { diff --git a/src/dashboard/livetvtuner.js b/src/dashboard/livetvtuner.js index 1cc806d05b..8d27093af1 100644 --- a/src/dashboard/livetvtuner.js +++ b/src/dashboard/livetvtuner.js @@ -8,12 +8,14 @@ define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button function fillTypes(view, currentId) { ApiClient.getJSON(ApiClient.getUrl("LiveTv/TunerHosts/Types")).then(function(types) { var selectType = view.querySelector(".selectType"); - selectType.innerHTML = types.map(function(t) { - return '"; + var html = ""; + html += types.map(function(tuner) { + return '"; }).join(""); - selectType.innerHTML += '"; + html += '"; + selectType.innerHTML = html; selectType.disabled = null != currentId; selectType.value = ""; @@ -39,9 +41,10 @@ define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button var selectType = view.querySelector(".selectType"); var type = info.Type || ""; if (info.Source && isM3uVariant(info.Source)) { - selectType.value = info.Source; - onTypeChange.call(selectType); + type = info.Source; } + selectType.value = type; + onTypeChange.call(selectType); view.querySelector(".txtDevicePath").value = info.Url || ""; view.querySelector(".txtFriendlyName").value = info.FriendlyName || ""; view.querySelector(".txtUserAgent").value = info.UserAgent || ""; diff --git a/src/scripts/notificationsettings.js b/src/scripts/notificationsettings.js index 317abce620..b167ca00e4 100644 --- a/src/scripts/notificationsettings.js +++ b/src/scripts/notificationsettings.js @@ -7,10 +7,10 @@ define(["loading", "libraryMenu", "globalize", "listViewStyle", "emby-linkbutton var html = ""; var lastCategory = ""; var showHelp = true; - html += list.map(function(i) { + html += list.map(function(notification) { var itemHtml = ""; - if (i.Category !== lastCategory) { - lastCategory = i.Category; + if (notification.Category !== lastCategory) { + lastCategory = notification.Category; if (lastCategory) { itemHtml += "
"; itemHtml += "
"; @@ -18,7 +18,7 @@ define(["loading", "libraryMenu", "globalize", "listViewStyle", "emby-linkbutton itemHtml += '
'; itemHtml += '
'; itemHtml += '

'; - itemHtml += i.Category; + itemHtml += notification.Category; itemHtml += "

"; if (showHelp) { showHelp = false; @@ -29,14 +29,14 @@ define(["loading", "libraryMenu", "globalize", "listViewStyle", "emby-linkbutton itemHtml += "
"; itemHtml += '
'; } - itemHtml += ''; - if (i.Enabled) { + itemHtml += ''; + if (notification.Enabled) { itemHtml += 'notifications_active'; } else { itemHtml += 'notifications_off'; } itemHtml += '
'; - itemHtml += '
' + i.Name + "
"; + itemHtml += '
' + notification.Name + "
"; itemHtml += "
"; itemHtml += ''; itemHtml += "
"; diff --git a/src/scripts/plugincatalogpage.js b/src/scripts/plugincatalogpage.js index f18c56f2f0..b399ba098a 100644 --- a/src/scripts/plugincatalogpage.js +++ b/src/scripts/plugincatalogpage.js @@ -59,15 +59,19 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-linkbutton", " return 0; }); - var i__q; var length; var plugin; var currentCategory; var html = ""; var hasOpenTag = false; - for (currentCategory = null, false === options.showCategory && (html += '
', hasOpenTag = true), i__q = 0, length = availablePlugins.length; i__q < length; i__q++) { - plugin = availablePlugins[i__q]; + currentCategory = null; + if (options.showCategory === false) { + html += '
'; + hasOpenTag = true; + } + for (var i = 0; i < availablePlugins.length; i++) { + plugin = availablePlugins[i]; var category = plugin.categoryDisplayName; if (category != currentCategory) { @@ -77,16 +81,13 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-linkbutton", " html += "
"; html += "
"; } - html += '
'; html += '

' + category + "

"; html += '
'; hasOpenTag = true; } - currentCategory = category; } - html += getPluginHtml(plugin, options, installedPlugins); } From c7a80764382eef572b3ddb4c1eda22602b0a3efc Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 9 Mar 2019 11:45:48 +0900 Subject: [PATCH 064/220] mirror the metadata manager in the user preference menu --- src/mypreferencesmenu.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/mypreferencesmenu.html b/src/mypreferencesmenu.html index 13bf648440..7269fe3521 100644 --- a/src/mypreferencesmenu.html +++ b/src/mypreferencesmenu.html @@ -82,6 +82,16 @@
+
From 326d9f9adfb2c7c47ad563ca001276ba96ae551a Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 9 Mar 2019 11:48:31 +0900 Subject: [PATCH 065/220] fix title capitalization --- src/strings/en-us.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index c8a73f205a..5ac13f0aad 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -563,7 +563,7 @@ "HeaderGuideProviders": "TV Guide Data Providers", "HeaderHomePage": "Home Page", "HeaderHomeScreen": "Home Screen", - "HeaderHomeScreenSettings": "Home Screen settings", + "HeaderHomeScreenSettings": "Home Screen Settings", "HeaderHttpHeaders": "Http Headers", "HeaderIdentification": "Identification", "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.", From a0e45f780968986f5abbc3e0cb1560a2aae18622 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 9 Mar 2019 17:35:38 +0000 Subject: [PATCH 066/220] ensure that appHost is loaded on onAppReady for all function --- src/scripts/site.js | 147 ++++++++++++++++++++++---------------------- 1 file changed, 75 insertions(+), 72 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index e7e06cfd46..4dfb67d73a 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1209,86 +1209,89 @@ var AppInfo = {}; function onAppReady(browser) { console.log("Begin onAppReady"); - var isInBackground = -1 !== self.location.href.toString().toLowerCase().indexOf("start=backgroundsync"); + // ensure that appHost is loaded in this point + require(['appHost'], function (appHost) { + var isInBackground = -1 !== self.location.href.toString().toLowerCase().indexOf("start=backgroundsync"); - window.Emby = {}; + window.Emby = {}; - console.log("onAppReady - loading dependencies"); + console.log("onAppReady - loading dependencies"); - if (isInBackground) { - syncNow(); - } else { + if (isInBackground) { + syncNow(); + } else { - if (browser.iOS) { - require(['css!devices/ios/ios.css']); - } + if (browser.iOS) { + require(['css!devices/ios/ios.css']); + } - require(['apphost', 'appRouter', 'scripts/themeloader', 'libraryMenu'], function (appHost, pageObjects) { - window.Emby.Page = pageObjects; + require(['appRouter', 'scripts/themeloader', 'libraryMenu'], function (pageObjects) { + window.Emby.Page = pageObjects; - defineCoreRoutes(appHost); + defineCoreRoutes(appHost); - Emby.Page.start({ - click: false, - hashbang: true + Emby.Page.start({ + click: false, + hashbang: true + }); + + if (!enableNativeGamepadKeyMapping() && isGamepadSupported()) { + require(["bower_components/emby-webcomponents/input/gamepadtokey"]); + } + + require(["bower_components/emby-webcomponents/thememediaplayer", "scripts/autobackdrops"]); + + if ("cordova" === self.appMode || "android" === self.appMode) { + if (browser.android) { + require(["cordova/mediasession", "cordova/chromecast", "cordova/appshortcuts"]); + } else if (browser.safari) { + require(["cordova/mediasession", "cordova/volume", "cordova/statusbar", "cordova/backgroundfetch"]); + } + } + + if (!browser.tv && !browser.xboxOne && !browser.ps4) { + require(["bower_components/emby-webcomponents/nowplayingbar/nowplayingbar"]); + } + + if (appHost.supports("remotecontrol")) { + require(["playerSelectionMenu", "bower_components/emby-webcomponents/playback/remotecontrolautoplay"]); + } + + if (!(appHost.supports("physicalvolumecontrol") && !browser.touch || browser.edge)) { + require(["bower_components/emby-webcomponents/playback/volumeosd"]); + } + + if (navigator.mediaSession) { + require(["mediaSession"]); + } + + require(["apiInput", "mouseManager"]); + + if (!browser.tv && !browser.xboxOne) { + require(["bower_components/emby-webcomponents/playback/playbackorientation"]); + registerServiceWorker(); + + if (window.Notification) { + require(["bower_components/emby-webcomponents/notifications/notifications"]); + } + } + + require(["playerSelectionMenu"]); + + if (appHost.supports("fullscreenchange") && (browser.edgeUwp || -1 !== navigator.userAgent.toLowerCase().indexOf("electron"))) { + require(["fullscreen-doubleclick"]); + } + + if (appHost.supports("sync")) { + initLocalSyncEvents(); + } + + if (!AppInfo.isNativeApp && window.ApiClient) { + require(["css!" + ApiClient.getUrl("Branding/Css")]); + } }); - - if (!enableNativeGamepadKeyMapping() && isGamepadSupported()) { - require(["bower_components/emby-webcomponents/input/gamepadtokey"]); - } - - require(["bower_components/emby-webcomponents/thememediaplayer", "scripts/autobackdrops"]); - - if ("cordova" === self.appMode || "android" === self.appMode) { - if (browser.android) { - require(["cordova/mediasession", "cordova/chromecast", "cordova/appshortcuts"]); - } else if (browser.safari) { - require(["cordova/mediasession", "cordova/volume", "cordova/statusbar", "cordova/backgroundfetch"]); - } - } - - if (!browser.tv && !browser.xboxOne && !browser.ps4) { - require(["bower_components/emby-webcomponents/nowplayingbar/nowplayingbar"]); - } - - if (appHost.supports("remotecontrol")) { - require(["playerSelectionMenu", "bower_components/emby-webcomponents/playback/remotecontrolautoplay"]); - } - - if (!(appHost.supports("physicalvolumecontrol") && !browser.touch || browser.edge)) { - require(["bower_components/emby-webcomponents/playback/volumeosd"]); - } - - if (navigator.mediaSession) { - require(["mediaSession"]); - } - - require(["apiInput", "mouseManager"]); - - if (!browser.tv && !browser.xboxOne) { - require(["bower_components/emby-webcomponents/playback/playbackorientation"]); - registerServiceWorker(); - - if (window.Notification) { - require(["bower_components/emby-webcomponents/notifications/notifications"]); - } - } - - require(["playerSelectionMenu"]); - - if (appHost.supports("fullscreenchange") && (browser.edgeUwp || -1 !== navigator.userAgent.toLowerCase().indexOf("electron"))) { - require(["fullscreen-doubleclick"]); - } - - if (appHost.supports("sync")) { - initLocalSyncEvents(); - } - - if (!AppInfo.isNativeApp && window.ApiClient) { - require(["css!" + ApiClient.getUrl("Branding/Css")]); - } - }); - } + } + }); } function registerServiceWorker() { From cd13be84fc3d755db25947033a5a91a9d5fad345 Mon Sep 17 00:00:00 2001 From: dkanada Date: Sun, 10 Mar 2019 07:06:28 +0900 Subject: [PATCH 067/220] revert network share path changes --- .../directorybrowser/directorybrowser.js | 16 ++++++++++- src/dashboard/dashboardgeneral.js | 27 +++++-------------- src/dashboardgeneral.html | 11 +------- 3 files changed, 23 insertions(+), 31 deletions(-) diff --git a/src/components/directorybrowser/directorybrowser.js b/src/components/directorybrowser/directorybrowser.js index 592885721b..c6d811e959 100644 --- a/src/components/directorybrowser/directorybrowser.js +++ b/src/components/directorybrowser/directorybrowser.js @@ -131,6 +131,14 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'emby-b if (!readOnlyAttribute) { html += '
'; } + if (options.enableNetworkSharePath) { + html += '
'; + html += ''; + html += '
'; + html += Globalize.translate("LabelOptionalNetworkPathHelp"); + html += "
"; + html += "
"; + } html += '
'; html += '"; html += "
"; @@ -211,8 +219,10 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'emby-b content.querySelector("form").addEventListener("submit", function(e) { if (options.callback) { + var networkSharePath = this.querySelector("#txtNetworkPath"); + networkSharePath = networkSharePath ? networkSharePath.value : null; var path = this.querySelector("#txtDirectoryPickerPath").value; - validatePath(path, options.validateWriteable, ApiClient).then(options.callback(path)); + validatePath(path, options.validateWriteable, ApiClient).then(options.callback(path, networkSharePath)); } e.preventDefault(); e.stopPropagation(); @@ -279,6 +289,10 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'emby-b }); currentDialog = dlg; dlg.querySelector("#txtDirectoryPickerPath").value = initialPath; + var txtNetworkPath = dlg.querySelector("#txtNetworkPath"); + if (txtNetworkPath) { + txtNetworkPath.value = options.networkSharePath || ""; + } if (!options.pathReadOnly) { refreshDirectoryBrowser(dlg, initialPath, fileOptions, true); } diff --git a/src/dashboard/dashboardgeneral.js b/src/dashboard/dashboardgeneral.js index c2f48a2803..c0ff217ffe 100644 --- a/src/dashboard/dashboardgeneral.js +++ b/src/dashboard/dashboardgeneral.js @@ -91,33 +91,20 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb var picker = new directoryBrowser(); picker.show({ path: $("#txtMetadataPath", view).val(), - callback: function(path) { + networkSharePath: $("#txtMetadataNetworkPath", view).val(), + callback: function(path, networkPath) { if (path) { $("#txtMetadataPath", view).val(path); } + if (networkPath) { + $("#txtMetadataNetworkPath", view).val(networkPath)); + } picker.close(); }, validateWriteable: true, header: Globalize.translate("HeaderSelectMetadataPath"), - instruction: Globalize.translate("HeaderSelectMetadataPathHelp") - }) - }) - }); - - $("#btnSelectMetadataNetworkPath", view).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser(); - picker.show({ - path: $("#txtMetadataNetworkPath", view).val(), - callback: function(path) { - if (path) { - $("#txtMetadataNetworkPath", view).val(path); - } - picker.close(); - }, - validateWriteable: true, - header: Globalize.translate("LabelOptionalNetworkPath"), - instruction: Globalize.translate("LabelOptionalNetworkPathHelp") + instruction: Globalize.translate("HeaderSelectMetadataPathHelp"), + enableNetworkSharePath: true }) }) }); diff --git a/src/dashboardgeneral.html b/src/dashboardgeneral.html index 4c56fa300b..f95246708f 100644 --- a/src/dashboardgeneral.html +++ b/src/dashboardgeneral.html @@ -53,16 +53,7 @@
${LabelMetadataPathHelp}
-
- -
-
-
- -
- -
-
${LabelOptionalNetworkPathHelp}
+
From 9ba1961a0c4f22aca3b3804e33e07adc12287af0 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Mon, 11 Mar 2019 08:24:26 +0100 Subject: [PATCH 068/220] Sort item results in the same order as requested --- .../emby-webcomponents/playback/playbackmanager.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/bower_components/emby-webcomponents/playback/playbackmanager.js b/src/bower_components/emby-webcomponents/playback/playbackmanager.js index 59a7ffd8bb..c506334a18 100644 --- a/src/bower_components/emby-webcomponents/playback/playbackmanager.js +++ b/src/bower_components/emby-webcomponents/playback/playbackmanager.js @@ -1806,6 +1806,12 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla } function translateItemsForPlayback(items, options) { + if (items.length > 1) { + // Use the original request id array for sorting the result in the proper order + items.sort(function (a, b) { + return options.ids.indexOf(a.Id) - options.ids.indexOf(b.Id); + }); + } var firstItem = items[0]; var promise; From 5ce13990b67f31f8e22c7db4ef6fd7a6f32ea833 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Mon, 11 Mar 2019 08:30:36 +0100 Subject: [PATCH 069/220] Add some extra null handling just in case --- .../emby-webcomponents/playback/playbackmanager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bower_components/emby-webcomponents/playback/playbackmanager.js b/src/bower_components/emby-webcomponents/playback/playbackmanager.js index c506334a18..b0904c4e96 100644 --- a/src/bower_components/emby-webcomponents/playback/playbackmanager.js +++ b/src/bower_components/emby-webcomponents/playback/playbackmanager.js @@ -1806,7 +1806,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla } function translateItemsForPlayback(items, options) { - if (items.length > 1) { + if (items.length > 1 && options && options.ids) { // Use the original request id array for sorting the result in the proper order items.sort(function (a, b) { return options.ids.indexOf(a.Id) - options.ids.indexOf(b.Id); From 023a1ed72f4145fb0af518b4496b051a28918775 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Mon, 11 Mar 2019 20:52:12 +0000 Subject: [PATCH 070/220] TODO for url prefix support investigation --- src/scripts/site.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/scripts/site.js b/src/scripts/site.js index 4dfb67d73a..c407d23b7c 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -57,6 +57,8 @@ var Dashboard = { getCurrentUser: function () { return window.ApiClient.getCurrentUser(false); }, + + //TODO: investigate url prefix support for serverAddress function serverAddress: function () { if (AppInfo.isNativeApp) { var apiClient = window.ApiClient; From 487ba61a42ab6ac98204a671daec4d8ebb56fe63 Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 11 Mar 2019 15:58:44 -0700 Subject: [PATCH 071/220] remove open subtitles page from dashboard --- src/opensubtitles.html | 27 --------------------------- src/scripts/librarymenu.js | 5 ----- src/scripts/opensubtitles.js | 36 ------------------------------------ src/scripts/site.js | 5 ----- 4 files changed, 73 deletions(-) delete mode 100644 src/opensubtitles.html delete mode 100644 src/scripts/opensubtitles.js diff --git a/src/opensubtitles.html b/src/opensubtitles.html deleted file mode 100644 index 51e337ae63..0000000000 --- a/src/opensubtitles.html +++ /dev/null @@ -1,27 +0,0 @@ -
-
-
- -
- -
- -
-
-
- - -
-
- -
-
- -
-
${SubtitleDownloadInstructions}
- -
-
-
diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index a637a779c4..fb4d100971 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -300,11 +300,6 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " icon: "swap_horiz", href: "encodingsettings.html", pageIds: ["encodingSettingsPage"] - }, { - name: "Open Subtitles", - href: "opensubtitles.html", - pageIds: ["openSubtitlesPage"], - icon: "closed_caption" }]; addPluginPagesToMainMenu(links, pluginItems, "server"); links.push({ diff --git a/src/scripts/opensubtitles.js b/src/scripts/opensubtitles.js deleted file mode 100644 index 99ec982dc1..0000000000 --- a/src/scripts/opensubtitles.js +++ /dev/null @@ -1,36 +0,0 @@ -define(["loading", "fnchecked", "emby-linkbutton", "emby-input", "emby-checkbox", "emby-button"], function (loading) { - "use strict"; - - function loadPage(page, config) { - page.querySelector("#txtOpenSubtitleUsername").value = config.OpenSubtitlesUsername; - page.querySelector("#txtOpenSubtitlePassword").value = config.OpenSubtitlesPasswordHash || ""; - loading.hide(); - } - - function onSubmit(evt) { - evt.preventDefault(); - loading.show(); - var form = this; - ApiClient.getNamedConfiguration("subtitles").then(function (config) { - config.OpenSubtitlesUsername = form.querySelector("#txtOpenSubtitleUsername").value; - var newPassword = form.querySelector("#txtOpenSubtitlePassword").value; - - if (newPassword) { - config.OpenSubtitlesPasswordHash = newPassword; - } - - ApiClient.updateNamedConfiguration("subtitles", config).then(Dashboard.processServerConfigurationUpdateResult); - }); - return false; - } - - $(document).on("pageinit", "#openSubtitlesPage", function() { - $(".metadataSubtitlesForm").off("submit", onSubmit).on("submit", onSubmit) - }).on("pageshow", "#openSubtitlesPage", function() { - loading.show(); - var page = this; - ApiClient.getNamedConfiguration("subtitles").then(function (response) { - loadPage(page, response); - }); - }); -}); diff --git a/src/scripts/site.js b/src/scripts/site.js index c012caba9e..78122b3c36 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -498,11 +498,6 @@ var Dashboard = { dependencies: [], autoFocus: !1, roles: "admin" - }), defineRoute({ - path: "/opensubtitles.html", - dependencies: [], - autoFocus: !1, - roles: "admin" }), defineRoute({ path: "/forgotpassword.html", dependencies: ["emby-input", "emby-button"], From 9d462263b9523f34d454a3e02ac04819c24638c7 Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 11 Mar 2019 21:31:33 -0700 Subject: [PATCH 072/220] add web path as config option --- src/dashboard.html | 8 +++++++- src/dashboard/dashboardgeneral.js | 17 +++++++++++++++++ src/dashboardgeneral.html | 10 ++++++++++ src/scripts/dashboardpage.js | 5 +++-- src/strings/en-us.json | 3 +++ 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/dashboard.html b/src/dashboard.html index d2de21f166..6c751740c3 100644 --- a/src/dashboard.html +++ b/src/dashboard.html @@ -109,7 +109,13 @@
${LabelTranscodingTemporaryFiles}
-
+
+
+
+
+
+
${LabelWeb}
+
diff --git a/src/dashboard/dashboardgeneral.js b/src/dashboard/dashboardgeneral.js index c0ff217ffe..6ef1c4d221 100644 --- a/src/dashboard/dashboardgeneral.js +++ b/src/dashboard/dashboardgeneral.js @@ -109,6 +109,23 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb }) }); + $("#btnSelectWebPath", view).on("click.selectDirectory", function() { + require(["directorybrowser"], function(directoryBrowser) { + var picker = new directoryBrowser; + picker.show({ + callback: function(path) { + if (path) { + view.querySelector("#txtWebPath").value = path; + } + picker.close(); + }, + validateWriteable: true, + header: Globalize.translate("LabelWebPath"), + instruction: Globalize.translate("LabelWebPathHelp") + }) + }) + }); + $(".dashboardGeneralForm", view).off("submit", onSubmit).on("submit", onSubmit); view.addEventListener("viewshow", function() { var promiseConfig = ApiClient.getServerConfiguration(); diff --git a/src/dashboardgeneral.html b/src/dashboardgeneral.html index f95246708f..8cc1177167 100644 --- a/src/dashboardgeneral.html +++ b/src/dashboardgeneral.html @@ -55,6 +55,16 @@
${LabelMetadataPathHelp}
+ +
+
+
+ +
+ +
+
${LabelWebPathHelp}
+
diff --git a/src/scripts/dashboardpage.js b/src/scripts/dashboardpage.js index f7bbc86866..0dc1f4e6fa 100644 --- a/src/scripts/dashboardpage.js +++ b/src/scripts/dashboardpage.js @@ -383,7 +383,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa for (var i = 0, length = tasks.length; i < length; i++) { var task = tasks[i]; - + html += "

"; html += task.Name + "
"; if (task.State === "Running") { @@ -407,8 +407,9 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa renderPaths: function (page, systemInfo) { page.querySelector("#cachePath").innerHTML = systemInfo.CachePath; page.querySelector("#logPath").innerHTML = systemInfo.LogPath; - page.querySelector("#transcodingTemporaryPath").innerHTML = systemInfo.TranscodingTempPath; + page.querySelector("#transcodePath").innerHTML = systemInfo.TranscodingTempPath; page.querySelector("#metadataPath").innerHTML = systemInfo.InternalMetadataPath; + page.querySelector("#webPath").innerHTML = systemInfo.WebPath; }, startInterval: function (apiClient) { apiClient.sendMessage("SessionsStart", "0,1500"); diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 5ac13f0aad..6fe64cdf4a 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -1122,6 +1122,8 @@ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata.", + "LabelWebPath": "Web path:", + "LabelWebPathHelp": "The path where the web client source is located.", "LabelMetadataReaders": "Metadata readers:", "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.", "LabelMetadataSavers": "Metadata savers:", @@ -1329,6 +1331,7 @@ "LabelVideoCodec": "Video: {0}", "LabelVideoType": "Video Type:", "LabelView": "View:", + "LabelWeb": "Web", "LabelWebsite": "Website:", "LabelWindowBackgroundColor": "Text background color:", "LabelXDlnaCap": "X-Dlna cap:", From 1fa4307b62203d77ff1c2a2f64d1bb9e92b1e0ae Mon Sep 17 00:00:00 2001 From: Anthony Lavado Date: Tue, 12 Mar 2019 15:16:28 -0400 Subject: [PATCH 073/220] Update translation help link Updates the link after the docs reorganization that happened. --- src/dashboardgeneral.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dashboardgeneral.html b/src/dashboardgeneral.html index f95246708f..94eeb23718 100644 --- a/src/dashboardgeneral.html +++ b/src/dashboardgeneral.html @@ -18,7 +18,7 @@

${LabelPreferredDisplayLanguageHelp}
From 1cb487b9a39a4155c5f448da906b445a7497eb85 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Tue, 12 Mar 2019 21:41:46 +0000 Subject: [PATCH 074/220] merge from upstream --- src/components/apiInput/apiInput.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/apiInput/apiInput.js b/src/components/apiInput/apiInput.js index e6cb3d312c..c12f933553 100644 --- a/src/components/apiInput/apiInput.js +++ b/src/components/apiInput/apiInput.js @@ -235,7 +235,7 @@ define(['connectionManager', 'playbackManager', 'events', 'inputManager', 'focus } function enableNativeGamepadKeyMapping() { - if (!(!window.navigator || "string" != typeof window.navigator.gamepadInputEmulation)) { + if (window.navigator && "string" == typeof window.navigator.gamepadInputEmulation) { window.navigator.gamepadInputEmulation = "keyboard"; return true; } From 6cbd26531c4befe30eed2946cdd4a76d86290179 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Tue, 12 Mar 2019 22:49:13 +0000 Subject: [PATCH 075/220] fix bug apphost naming resolution --- src/scripts/site.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 7c121ad943..75549cab3a 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1181,7 +1181,7 @@ var AppInfo = {}; console.log("Begin onAppReady"); // ensure that appHost is loaded in this point - require(['appHost'], function (appHost) { + require(['apphost'], function (appHost) { var isInBackground = -1 !== self.location.href.toString().toLowerCase().indexOf("start=backgroundsync"); window.Emby = {}; From 44fe392912d85449c37892a9a198a355486b4d84 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Tue, 12 Mar 2019 23:28:26 +0000 Subject: [PATCH 076/220] rename embyWebComponentsBower to components --- src/components/skinmanager.js | 4 +- src/scripts/site.js | 312 +++++++++++++++++----------------- 2 files changed, 157 insertions(+), 159 deletions(-) diff --git a/src/components/skinmanager.js b/src/components/skinmanager.js index 556250137a..5893a845e8 100644 --- a/src/components/skinmanager.js +++ b/src/components/skinmanager.js @@ -219,10 +219,8 @@ define(['apphost', 'userSettings', 'browser', 'events', 'pluginManager', 'backdr selectedTheme = defaultTheme; } - var embyWebComponentsBowerPath = 'components'; - return { - stylesheetPath: require.toUrl(embyWebComponentsBowerPath + '/themes/' + selectedTheme.id + '/theme.css'), + stylesheetPath: require.toUrl('components/themes/' + selectedTheme.id + '/theme.css'), themeId: selectedTheme.id }; } diff --git a/src/scripts/site.js b/src/scripts/site.js index 75549cab3a..fc24fe3b2e 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -427,24 +427,24 @@ var AppInfo = {}; function initRequireWithBrowser(browser) { var bowerPath = getBowerPath(); var apiClientBowerPath = bowerPath + "/emby-apiclient"; - var embyWebComponentsBowerPath = "components"; + var componentsPath = "components"; if ("android" === self.appMode) { define("filesystem", ["cordova/filesystem"], returnFirstDependency); } else { - define("filesystem", [embyWebComponentsBowerPath + "/filesystem"], returnFirstDependency); + define("filesystem", [componentsPath + "/filesystem"], returnFirstDependency); } if (window.IntersectionObserver && !browser.edge) { - define("lazyLoader", [embyWebComponentsBowerPath + "/lazyloader/lazyloader-intersectionobserver"], returnFirstDependency); + define("lazyLoader", [componentsPath + "/lazyloader/lazyloader-intersectionobserver"], returnFirstDependency); } else { - define("lazyLoader", [embyWebComponentsBowerPath + "/lazyloader/lazyloader-scroll"], returnFirstDependency); + define("lazyLoader", [componentsPath + "/lazyloader/lazyloader-scroll"], returnFirstDependency); } if ("android" === self.appMode) { define("shell", ["cordova/shell"], returnFirstDependency); } else { - define("shell", [embyWebComponentsBowerPath + "/shell"], returnFirstDependency); + define("shell", [componentsPath + "/shell"], returnFirstDependency); } if ("cordova" === self.appMode || "android" === self.appMode) { @@ -471,40 +471,40 @@ var AppInfo = {}; if ("cordova" === self.appMode && browser.iOSVersion && browser.iOSVersion < 11) { define("imageFetcher", ["cordova/imagestore"], returnFirstDependency); } else { - define("imageFetcher", [embyWebComponentsBowerPath + "/images/basicimagefetcher"], returnFirstDependency); + define("imageFetcher", [componentsPath + "/images/basicimagefetcher"], returnFirstDependency); } var preferNativeAlerts = browser.tv; - define("alert", [embyWebComponentsBowerPath + "/alert"], returnFirstDependency); + define("alert", [componentsPath + "/alert"], returnFirstDependency); defineResizeObserver(); - define("dialog", [embyWebComponentsBowerPath + "/dialog/dialog"], returnFirstDependency); + define("dialog", [componentsPath + "/dialog/dialog"], returnFirstDependency); if (preferNativeAlerts && window.confirm) { - define("confirm", [embyWebComponentsBowerPath + "/confirm/nativeconfirm"], returnFirstDependency); + define("confirm", [componentsPath + "/confirm/nativeconfirm"], returnFirstDependency); } else { - define("confirm", [embyWebComponentsBowerPath + "/confirm/confirm"], returnFirstDependency); + define("confirm", [componentsPath + "/confirm/confirm"], returnFirstDependency); } if ((preferNativeAlerts || browser.xboxOne) && window.confirm) { - define("prompt", [embyWebComponentsBowerPath + "/prompt/nativeprompt"], returnFirstDependency); + define("prompt", [componentsPath + "/prompt/nativeprompt"], returnFirstDependency); } else { - define("prompt", [embyWebComponentsBowerPath + "/prompt/prompt"], returnFirstDependency); + define("prompt", [componentsPath + "/prompt/prompt"], returnFirstDependency); } if (browser.tizen || browser.operaTv || browser.chromecast || browser.orsay || browser.web0s || browser.ps4) { - define("loading", [embyWebComponentsBowerPath + "/loading/loading-legacy"], returnFirstDependency); + define("loading", [componentsPath + "/loading/loading-legacy"], returnFirstDependency); } else { - define("loading", [embyWebComponentsBowerPath + "/loading/loading-lite"], returnFirstDependency); + define("loading", [componentsPath + "/loading/loading-lite"], returnFirstDependency); } - define("multi-download", [embyWebComponentsBowerPath + "/multidownload"], returnFirstDependency); + define("multi-download", [componentsPath + "/multidownload"], returnFirstDependency); if ("android" === self.appMode) { define("fileDownloader", ["cordova/filedownloader"], returnFirstDependency); } else { - define("fileDownloader", [embyWebComponentsBowerPath + "/filedownloader"], returnFirstDependency); + define("fileDownloader", [componentsPath + "/filedownloader"], returnFirstDependency); } define("localassetmanager", [apiClientBowerPath + "/localassetmanager"], returnFirstDependency); @@ -1306,11 +1306,11 @@ var AppInfo = {}; var urlArgs = "v=" + (window.dashboardVersion || new Date().getDate()); var bowerPath = getBowerPath(); var apiClientBowerPath = bowerPath + "/emby-apiclient"; - var embyWebComponentsBowerPath = "components"; + var componentsPath = "components"; var paths = { velocity: bowerPath + "/velocity/velocity.min", vibrant: bowerPath + "/vibrant/dist/vibrant", - staticBackdrops: embyWebComponentsBowerPath + "/staticbackdrops", + staticBackdrops: componentsPath + "/staticbackdrops", ironCardList: "components/ironcardlist/ironcardlist", scrollThreshold: "components/scrollthreshold", playlisteditor: "components/playlisteditor/playlisteditor", @@ -1326,114 +1326,114 @@ var AppInfo = {}; events: apiClientBowerPath + "/events", credentialprovider: apiClientBowerPath + "/credentials", connectionManagerFactory: bowerPath + "/emby-apiclient/connectionmanager", - visibleinviewport: embyWebComponentsBowerPath + "/visibleinviewport", - browserdeviceprofile: embyWebComponentsBowerPath + "/browserdeviceprofile", - browser: embyWebComponentsBowerPath + "/browser", - inputManager: embyWebComponentsBowerPath + "/inputmanager", - qualityoptions: embyWebComponentsBowerPath + "/qualityoptions", + visibleinviewport: componentsPath + "/visibleinviewport", + browserdeviceprofile: componentsPath + "/browserdeviceprofile", + browser: componentsPath + "/browser", + inputManager: componentsPath + "/inputmanager", + qualityoptions: componentsPath + "/qualityoptions", hammer: bowerPath + "/hammerjs/hammer.min", - pageJs: embyWebComponentsBowerPath + "/pagejs/page", - focusManager: embyWebComponentsBowerPath + "/focusmanager", - datetime: embyWebComponentsBowerPath + "/datetime", - globalize: embyWebComponentsBowerPath + "/globalize", - itemHelper: embyWebComponentsBowerPath + "/itemhelper", - itemShortcuts: embyWebComponentsBowerPath + "/shortcuts", - playQueueManager: embyWebComponentsBowerPath + "/playback/playqueuemanager", - autoPlayDetect: embyWebComponentsBowerPath + "/playback/autoplaydetect", - nowPlayingHelper: embyWebComponentsBowerPath + "/playback/nowplayinghelper", - pluginManager: embyWebComponentsBowerPath + "/pluginmanager", - packageManager: embyWebComponentsBowerPath + "/packagemanager" + pageJs: componentsPath + "/pagejs/page", + focusManager: componentsPath + "/focusmanager", + datetime: componentsPath + "/datetime", + globalize: componentsPath + "/globalize", + itemHelper: componentsPath + "/itemhelper", + itemShortcuts: componentsPath + "/shortcuts", + playQueueManager: componentsPath + "/playback/playqueuemanager", + autoPlayDetect: componentsPath + "/playback/autoplaydetect", + nowPlayingHelper: componentsPath + "/playback/nowplayinghelper", + pluginManager: componentsPath + "/pluginmanager", + packageManager: componentsPath + "/packagemanager" }; paths.hlsjs = bowerPath + "/hlsjs/dist/hls.min"; - paths.flvjs = embyWebComponentsBowerPath + "/flvjs/flv.min"; - paths.shaka = embyWebComponentsBowerPath + "/shaka/shaka-player.compiled"; - define("chromecastHelper", [embyWebComponentsBowerPath + "/chromecast/chromecasthelpers"], returnFirstDependency); - define("mediaSession", [embyWebComponentsBowerPath + "/playback/mediasession"], returnFirstDependency); - define("actionsheet", [embyWebComponentsBowerPath + "/actionsheet/actionsheet"], returnFirstDependency); + paths.flvjs = componentsPath + "/flvjs/flv.min"; + paths.shaka = componentsPath + "/shaka/shaka-player.compiled"; + define("chromecastHelper", [componentsPath + "/chromecast/chromecasthelpers"], returnFirstDependency); + define("mediaSession", [componentsPath + "/playback/mediasession"], returnFirstDependency); + define("actionsheet", [componentsPath + "/actionsheet/actionsheet"], returnFirstDependency); define("libjass", [bowerPath + "/libjass/libjass.min", "css!" + bowerPath + "/libjass/libjass"], returnFirstDependency); define("tunerPicker", ["components/tunerpicker"], returnFirstDependency); - define("mainTabsManager", [embyWebComponentsBowerPath + "/maintabsmanager"], returnFirstDependency); - define("imageLoader", [embyWebComponentsBowerPath + "/images/imagehelper"], returnFirstDependency); - define("appFooter", [embyWebComponentsBowerPath + "/appfooter/appfooter"], returnFirstDependency); + define("mainTabsManager", [componentsPath + "/maintabsmanager"], returnFirstDependency); + define("imageLoader", [componentsPath + "/images/imagehelper"], returnFirstDependency); + define("appFooter", [componentsPath + "/appfooter/appfooter"], returnFirstDependency); define("directorybrowser", ["components/directorybrowser/directorybrowser"], returnFirstDependency); - define("metadataEditor", [embyWebComponentsBowerPath + "/metadataeditor/metadataeditor"], returnFirstDependency); - define("personEditor", [embyWebComponentsBowerPath + "/metadataeditor/personeditor"], returnFirstDependency); - define("playerSelectionMenu", [embyWebComponentsBowerPath + "/playback/playerselection"], returnFirstDependency); - define("playerSettingsMenu", [embyWebComponentsBowerPath + "/playback/playersettingsmenu"], returnFirstDependency); - define("playMethodHelper", [embyWebComponentsBowerPath + "/playback/playmethodhelper"], returnFirstDependency); - define("brightnessOsd", [embyWebComponentsBowerPath + "/playback/brightnessosd"], returnFirstDependency); + define("metadataEditor", [componentsPath + "/metadataeditor/metadataeditor"], returnFirstDependency); + define("personEditor", [componentsPath + "/metadataeditor/personeditor"], returnFirstDependency); + define("playerSelectionMenu", [componentsPath + "/playback/playerselection"], returnFirstDependency); + define("playerSettingsMenu", [componentsPath + "/playback/playersettingsmenu"], returnFirstDependency); + define("playMethodHelper", [componentsPath + "/playback/playmethodhelper"], returnFirstDependency); + define("brightnessOsd", [componentsPath + "/playback/brightnessosd"], returnFirstDependency); define("libraryMenu", ["scripts/librarymenu"], returnFirstDependency); - define("emby-collapse", [embyWebComponentsBowerPath + "/emby-collapse/emby-collapse"], returnFirstDependency); - define("emby-button", [embyWebComponentsBowerPath + "/emby-button/emby-button"], returnFirstDependency); + define("emby-collapse", [componentsPath + "/emby-collapse/emby-collapse"], returnFirstDependency); + define("emby-button", [componentsPath + "/emby-button/emby-button"], returnFirstDependency); define("emby-linkbutton", ["emby-button"], returnFirstDependency); - define("emby-itemscontainer", [embyWebComponentsBowerPath + "/emby-itemscontainer/emby-itemscontainer"], returnFirstDependency); - define("alphaNumericShortcuts", [embyWebComponentsBowerPath + "/alphanumericshortcuts/alphanumericshortcuts"], returnFirstDependency); - define("emby-scroller", [embyWebComponentsBowerPath + "/emby-scroller/emby-scroller"], returnFirstDependency); - define("emby-tabs", [embyWebComponentsBowerPath + "/emby-tabs/emby-tabs"], returnFirstDependency); - define("emby-scrollbuttons", [embyWebComponentsBowerPath + "/emby-scrollbuttons/emby-scrollbuttons"], returnFirstDependency); - define("emby-progressring", [embyWebComponentsBowerPath + "/emby-progressring/emby-progressring"], returnFirstDependency); - define("emby-itemrefreshindicator", [embyWebComponentsBowerPath + "/emby-itemrefreshindicator/emby-itemrefreshindicator"], returnFirstDependency); - define("multiSelect", [embyWebComponentsBowerPath + "/multiselect/multiselect"], returnFirstDependency); - define("alphaPicker", [embyWebComponentsBowerPath + "/alphapicker/alphapicker"], returnFirstDependency); - define("paper-icon-button-light", [embyWebComponentsBowerPath + "/emby-button/paper-icon-button-light"], returnFirstDependency); - define("tabbedView", [embyWebComponentsBowerPath + "/tabbedview/tabbedview"], returnFirstDependency); - define("itemsTab", [embyWebComponentsBowerPath + "/tabbedview/itemstab"], returnFirstDependency); - define("emby-input", [embyWebComponentsBowerPath + "/emby-input/emby-input"], returnFirstDependency); - define("emby-select", [embyWebComponentsBowerPath + "/emby-select/emby-select"], returnFirstDependency); - define("emby-slider", [embyWebComponentsBowerPath + "/emby-slider/emby-slider"], returnFirstDependency); - define("emby-checkbox", [embyWebComponentsBowerPath + "/emby-checkbox/emby-checkbox"], returnFirstDependency); - define("emby-toggle", [embyWebComponentsBowerPath + "/emby-toggle/emby-toggle"], returnFirstDependency); - define("emby-radio", [embyWebComponentsBowerPath + "/emby-radio/emby-radio"], returnFirstDependency); - define("emby-textarea", [embyWebComponentsBowerPath + "/emby-textarea/emby-textarea"], returnFirstDependency); - define("collectionEditor", [embyWebComponentsBowerPath + "/collectioneditor/collectioneditor"], returnFirstDependency); - define("serverRestartDialog", [embyWebComponentsBowerPath + "/serverrestartdialog/serverrestartdialog"], returnFirstDependency); - define("playlistEditor", [embyWebComponentsBowerPath + "/playlisteditor/playlisteditor"], returnFirstDependency); - define("recordingCreator", [embyWebComponentsBowerPath + "/recordingcreator/recordingcreator"], returnFirstDependency); - define("recordingEditor", [embyWebComponentsBowerPath + "/recordingcreator/recordingeditor"], returnFirstDependency); - define("seriesRecordingEditor", [embyWebComponentsBowerPath + "/recordingcreator/seriesrecordingeditor"], returnFirstDependency); - define("recordingFields", [embyWebComponentsBowerPath + "/recordingcreator/recordingfields"], returnFirstDependency); - define("recordingButton", [embyWebComponentsBowerPath + "/recordingcreator/recordingbutton"], returnFirstDependency); - define("recordingHelper", [embyWebComponentsBowerPath + "/recordingcreator/recordinghelper"], returnFirstDependency); - define("subtitleEditor", [embyWebComponentsBowerPath + "/subtitleeditor/subtitleeditor"], returnFirstDependency); - define("itemIdentifier", [embyWebComponentsBowerPath + "/itemidentifier/itemidentifier"], returnFirstDependency); - define("mediaInfo", [embyWebComponentsBowerPath + "/mediainfo/mediainfo"], returnFirstDependency); - define("itemContextMenu", [embyWebComponentsBowerPath + "/itemcontextmenu"], returnFirstDependency); - define("imageEditor", [embyWebComponentsBowerPath + "/imageeditor/imageeditor"], returnFirstDependency); - define("imageDownloader", [embyWebComponentsBowerPath + "/imagedownloader/imagedownloader"], returnFirstDependency); - define("dom", [embyWebComponentsBowerPath + "/dom"], returnFirstDependency); - define("playerStats", [embyWebComponentsBowerPath + "/playerstats/playerstats"], returnFirstDependency); - define("searchFields", [embyWebComponentsBowerPath + "/search/searchfields"], returnFirstDependency); - define("searchResults", [embyWebComponentsBowerPath + "/search/searchresults"], returnFirstDependency); - define("upNextDialog", [embyWebComponentsBowerPath + "/upnextdialog/upnextdialog"], returnFirstDependency); - define("fullscreen-doubleclick", [embyWebComponentsBowerPath + "/fullscreen/fullscreen-dc"], returnFirstDependency); - define("fullscreenManager", [embyWebComponentsBowerPath + "/fullscreen/fullscreenmanager", "events"], returnFirstDependency); - define("headroom", [embyWebComponentsBowerPath + "/headroom/headroom"], returnFirstDependency); - define("subtitleAppearanceHelper", [embyWebComponentsBowerPath + "/subtitlesettings/subtitleappearancehelper"], returnFirstDependency); - define("subtitleSettings", [embyWebComponentsBowerPath + "/subtitlesettings/subtitlesettings"], returnFirstDependency); - define("displaySettings", [embyWebComponentsBowerPath + "/displaysettings/displaysettings"], returnFirstDependency); - define("playbackSettings", [embyWebComponentsBowerPath + "/playbacksettings/playbacksettings"], returnFirstDependency); - define("homescreenSettings", [embyWebComponentsBowerPath + "/homescreensettings/homescreensettings"], returnFirstDependency); - define("homescreenSettingsDialog", [embyWebComponentsBowerPath + "/homescreensettings/homescreensettingsdialog"], returnFirstDependency); - define("playbackManager", [embyWebComponentsBowerPath + "/playback/playbackmanager"], getPlaybackManager); - define("layoutManager", [embyWebComponentsBowerPath + "/layoutmanager", "apphost"], getLayoutManager); - define("homeSections", [embyWebComponentsBowerPath + "/homesections/homesections"], returnFirstDependency); - define("playMenu", [embyWebComponentsBowerPath + "/playmenu"], returnFirstDependency); - define("refreshDialog", [embyWebComponentsBowerPath + "/refreshdialog/refreshdialog"], returnFirstDependency); - define("backdrop", [embyWebComponentsBowerPath + "/backdrop/backdrop"], returnFirstDependency); - define("fetchHelper", [embyWebComponentsBowerPath + "/fetchhelper"], returnFirstDependency); - define("roundCardStyle", ["cardStyle", "css!" + embyWebComponentsBowerPath + "/cardbuilder/roundcard"], returnFirstDependency); - define("cardStyle", ["css!" + embyWebComponentsBowerPath + "/cardbuilder/card"], returnFirstDependency); - define("cardBuilder", [embyWebComponentsBowerPath + "/cardbuilder/cardbuilder"], returnFirstDependency); - define("peoplecardbuilder", [embyWebComponentsBowerPath + "/cardbuilder/peoplecardbuilder"], returnFirstDependency); - define("chaptercardbuilder", [embyWebComponentsBowerPath + "/cardbuilder/chaptercardbuilder"], returnFirstDependency); - define("flexStyles", ["css!" + embyWebComponentsBowerPath + "/flexstyles"], returnFirstDependency); - define("deleteHelper", [embyWebComponentsBowerPath + "/deletehelper"], returnFirstDependency); - define("tvguide", [embyWebComponentsBowerPath + "/guide/guide"], returnFirstDependency); - define("programStyles", ["css!" + embyWebComponentsBowerPath + "/guide/programs"], returnFirstDependency); - define("guide-settings-dialog", [embyWebComponentsBowerPath + "/guide/guide-settings"], returnFirstDependency); - define("loadingDialog", [embyWebComponentsBowerPath + "/loadingdialog/loadingdialog"], returnFirstDependency); - define("syncDialog", [embyWebComponentsBowerPath + "/sync/sync"], returnFirstDependency); - define("viewManager", [embyWebComponentsBowerPath + "/viewmanager/viewmanager"], function (viewManager) { + define("emby-itemscontainer", [componentsPath + "/emby-itemscontainer/emby-itemscontainer"], returnFirstDependency); + define("alphaNumericShortcuts", [componentsPath + "/alphanumericshortcuts/alphanumericshortcuts"], returnFirstDependency); + define("emby-scroller", [componentsPath + "/emby-scroller/emby-scroller"], returnFirstDependency); + define("emby-tabs", [componentsPath + "/emby-tabs/emby-tabs"], returnFirstDependency); + define("emby-scrollbuttons", [componentsPath + "/emby-scrollbuttons/emby-scrollbuttons"], returnFirstDependency); + define("emby-progressring", [componentsPath + "/emby-progressring/emby-progressring"], returnFirstDependency); + define("emby-itemrefreshindicator", [componentsPath + "/emby-itemrefreshindicator/emby-itemrefreshindicator"], returnFirstDependency); + define("multiSelect", [componentsPath + "/multiselect/multiselect"], returnFirstDependency); + define("alphaPicker", [componentsPath + "/alphapicker/alphapicker"], returnFirstDependency); + define("paper-icon-button-light", [componentsPath + "/emby-button/paper-icon-button-light"], returnFirstDependency); + define("tabbedView", [componentsPath + "/tabbedview/tabbedview"], returnFirstDependency); + define("itemsTab", [componentsPath + "/tabbedview/itemstab"], returnFirstDependency); + define("emby-input", [componentsPath + "/emby-input/emby-input"], returnFirstDependency); + define("emby-select", [componentsPath + "/emby-select/emby-select"], returnFirstDependency); + define("emby-slider", [componentsPath + "/emby-slider/emby-slider"], returnFirstDependency); + define("emby-checkbox", [componentsPath + "/emby-checkbox/emby-checkbox"], returnFirstDependency); + define("emby-toggle", [componentsPath + "/emby-toggle/emby-toggle"], returnFirstDependency); + define("emby-radio", [componentsPath + "/emby-radio/emby-radio"], returnFirstDependency); + define("emby-textarea", [componentsPath + "/emby-textarea/emby-textarea"], returnFirstDependency); + define("collectionEditor", [componentsPath + "/collectioneditor/collectioneditor"], returnFirstDependency); + define("serverRestartDialog", [componentsPath + "/serverrestartdialog/serverrestartdialog"], returnFirstDependency); + define("playlistEditor", [componentsPath + "/playlisteditor/playlisteditor"], returnFirstDependency); + define("recordingCreator", [componentsPath + "/recordingcreator/recordingcreator"], returnFirstDependency); + define("recordingEditor", [componentsPath + "/recordingcreator/recordingeditor"], returnFirstDependency); + define("seriesRecordingEditor", [componentsPath + "/recordingcreator/seriesrecordingeditor"], returnFirstDependency); + define("recordingFields", [componentsPath + "/recordingcreator/recordingfields"], returnFirstDependency); + define("recordingButton", [componentsPath + "/recordingcreator/recordingbutton"], returnFirstDependency); + define("recordingHelper", [componentsPath + "/recordingcreator/recordinghelper"], returnFirstDependency); + define("subtitleEditor", [componentsPath + "/subtitleeditor/subtitleeditor"], returnFirstDependency); + define("itemIdentifier", [componentsPath + "/itemidentifier/itemidentifier"], returnFirstDependency); + define("mediaInfo", [componentsPath + "/mediainfo/mediainfo"], returnFirstDependency); + define("itemContextMenu", [componentsPath + "/itemcontextmenu"], returnFirstDependency); + define("imageEditor", [componentsPath + "/imageeditor/imageeditor"], returnFirstDependency); + define("imageDownloader", [componentsPath + "/imagedownloader/imagedownloader"], returnFirstDependency); + define("dom", [componentsPath + "/dom"], returnFirstDependency); + define("playerStats", [componentsPath + "/playerstats/playerstats"], returnFirstDependency); + define("searchFields", [componentsPath + "/search/searchfields"], returnFirstDependency); + define("searchResults", [componentsPath + "/search/searchresults"], returnFirstDependency); + define("upNextDialog", [componentsPath + "/upnextdialog/upnextdialog"], returnFirstDependency); + define("fullscreen-doubleclick", [componentsPath + "/fullscreen/fullscreen-dc"], returnFirstDependency); + define("fullscreenManager", [componentsPath + "/fullscreen/fullscreenmanager", "events"], returnFirstDependency); + define("headroom", [componentsPath + "/headroom/headroom"], returnFirstDependency); + define("subtitleAppearanceHelper", [componentsPath + "/subtitlesettings/subtitleappearancehelper"], returnFirstDependency); + define("subtitleSettings", [componentsPath + "/subtitlesettings/subtitlesettings"], returnFirstDependency); + define("displaySettings", [componentsPath + "/displaysettings/displaysettings"], returnFirstDependency); + define("playbackSettings", [componentsPath + "/playbacksettings/playbacksettings"], returnFirstDependency); + define("homescreenSettings", [componentsPath + "/homescreensettings/homescreensettings"], returnFirstDependency); + define("homescreenSettingsDialog", [componentsPath + "/homescreensettings/homescreensettingsdialog"], returnFirstDependency); + define("playbackManager", [componentsPath + "/playback/playbackmanager"], getPlaybackManager); + define("layoutManager", [componentsPath + "/layoutmanager", "apphost"], getLayoutManager); + define("homeSections", [componentsPath + "/homesections/homesections"], returnFirstDependency); + define("playMenu", [componentsPath + "/playmenu"], returnFirstDependency); + define("refreshDialog", [componentsPath + "/refreshdialog/refreshdialog"], returnFirstDependency); + define("backdrop", [componentsPath + "/backdrop/backdrop"], returnFirstDependency); + define("fetchHelper", [componentsPath + "/fetchhelper"], returnFirstDependency); + define("roundCardStyle", ["cardStyle", "css!" + componentsPath + "/cardbuilder/roundcard"], returnFirstDependency); + define("cardStyle", ["css!" + componentsPath + "/cardbuilder/card"], returnFirstDependency); + define("cardBuilder", [componentsPath + "/cardbuilder/cardbuilder"], returnFirstDependency); + define("peoplecardbuilder", [componentsPath + "/cardbuilder/peoplecardbuilder"], returnFirstDependency); + define("chaptercardbuilder", [componentsPath + "/cardbuilder/chaptercardbuilder"], returnFirstDependency); + define("flexStyles", ["css!" + componentsPath + "/flexstyles"], returnFirstDependency); + define("deleteHelper", [componentsPath + "/deletehelper"], returnFirstDependency); + define("tvguide", [componentsPath + "/guide/guide"], returnFirstDependency); + define("programStyles", ["css!" + componentsPath + "/guide/programs"], returnFirstDependency); + define("guide-settings-dialog", [componentsPath + "/guide/guide-settings"], returnFirstDependency); + define("loadingDialog", [componentsPath + "/loadingdialog/loadingdialog"], returnFirstDependency); + define("syncDialog", [componentsPath + "/sync/sync"], returnFirstDependency); + define("viewManager", [componentsPath + "/viewmanager/viewmanager"], function (viewManager) { window.ViewManager = viewManager; viewManager.dispatchPageEvents(true); return viewManager; @@ -1461,25 +1461,25 @@ var AppInfo = {}; requirejs.onError = onRequireJsError; define("jstree", ["thirdparty/jstree/jstree", "css!thirdparty/jstree/themes/default/style.css"], returnFirstDependency); define("dashboardcss", ["css!css/dashboard"], returnFirstDependency); - define("slideshow", [embyWebComponentsBowerPath + "/slideshow/slideshow"], returnFirstDependency); + define("slideshow", [componentsPath + "/slideshow/slideshow"], returnFirstDependency); define("fetch", [bowerPath + "/fetch/fetch"], returnFirstDependency); - define("raf", [embyWebComponentsBowerPath + "/polyfills/raf"], returnFirstDependency); - define("functionbind", [embyWebComponentsBowerPath + "/polyfills/bind"], returnFirstDependency); - define("arraypolyfills", [embyWebComponentsBowerPath + "/polyfills/array"], returnFirstDependency); - define("objectassign", [embyWebComponentsBowerPath + "/polyfills/objectassign"], returnFirstDependency); - define("clearButtonStyle", ["css!" + embyWebComponentsBowerPath + "/clearbutton"], returnFirstDependency); - define("userdataButtons", [embyWebComponentsBowerPath + "/userdatabuttons/userdatabuttons"], returnFirstDependency); - define("emby-playstatebutton", [embyWebComponentsBowerPath + "/userdatabuttons/emby-playstatebutton"], returnFirstDependency); - define("emby-ratingbutton", [embyWebComponentsBowerPath + "/userdatabuttons/emby-ratingbutton"], returnFirstDependency); - define("emby-downloadbutton", [embyWebComponentsBowerPath + "/sync/emby-downloadbutton"], returnFirstDependency); - define("listView", [embyWebComponentsBowerPath + "/listview/listview"], returnFirstDependency); - define("listViewStyle", ["css!" + embyWebComponentsBowerPath + "/listview/listview"], returnFirstDependency); - define("formDialogStyle", ["css!" + embyWebComponentsBowerPath + "/formdialog"], returnFirstDependency); - define("indicators", [embyWebComponentsBowerPath + "/indicators/indicators"], returnFirstDependency); - define("viewSettings", [embyWebComponentsBowerPath + "/viewsettings/viewsettings"], returnFirstDependency); - define("filterMenu", [embyWebComponentsBowerPath + "/filtermenu/filtermenu"], returnFirstDependency); - define("sortMenu", [embyWebComponentsBowerPath + "/sortmenu/sortmenu"], returnFirstDependency); - define("registrationServices", [embyWebComponentsBowerPath + "/registrationservices/registrationservices"], returnFirstDependency); + define("raf", [componentsPath + "/polyfills/raf"], returnFirstDependency); + define("functionbind", [componentsPath + "/polyfills/bind"], returnFirstDependency); + define("arraypolyfills", [componentsPath + "/polyfills/array"], returnFirstDependency); + define("objectassign", [componentsPath + "/polyfills/objectassign"], returnFirstDependency); + define("clearButtonStyle", ["css!" + componentsPath + "/clearbutton"], returnFirstDependency); + define("userdataButtons", [componentsPath + "/userdatabuttons/userdatabuttons"], returnFirstDependency); + define("emby-playstatebutton", [componentsPath + "/userdatabuttons/emby-playstatebutton"], returnFirstDependency); + define("emby-ratingbutton", [componentsPath + "/userdatabuttons/emby-ratingbutton"], returnFirstDependency); + define("emby-downloadbutton", [componentsPath + "/sync/emby-downloadbutton"], returnFirstDependency); + define("listView", [componentsPath + "/listview/listview"], returnFirstDependency); + define("listViewStyle", ["css!" + componentsPath + "/listview/listview"], returnFirstDependency); + define("formDialogStyle", ["css!" + componentsPath + "/formdialog"], returnFirstDependency); + define("indicators", [componentsPath + "/indicators/indicators"], returnFirstDependency); + define("viewSettings", [componentsPath + "/viewsettings/viewsettings"], returnFirstDependency); + define("filterMenu", [componentsPath + "/filtermenu/filtermenu"], returnFirstDependency); + define("sortMenu", [componentsPath + "/sortmenu/sortmenu"], returnFirstDependency); + define("registrationServices", [componentsPath + "/registrationservices/registrationservices"], returnFirstDependency); if ("cordova" === self.appMode || "android" === self.appMode) { define("fileupload", ["cordova/fileupload"], returnFirstDependency); @@ -1491,26 +1491,26 @@ var AppInfo = {}; define("serversync", [apiClientBowerPath + "/sync/serversync"], returnFirstDependency); define("multiserversync", [apiClientBowerPath + "/sync/multiserversync"], returnFirstDependency); define("mediasync", [apiClientBowerPath + "/sync/mediasync"], returnFirstDependency); - define("idb", [embyWebComponentsBowerPath + "/idb"], returnFirstDependency); - define("sanitizefilename", [embyWebComponentsBowerPath + "/sanitizefilename"], returnFirstDependency); + define("idb", [componentsPath + "/idb"], returnFirstDependency); + define("sanitizefilename", [componentsPath + "/sanitizefilename"], returnFirstDependency); define("itemrepository", [apiClientBowerPath + "/sync/itemrepository"], returnFirstDependency); define("useractionrepository", [apiClientBowerPath + "/sync/useractionrepository"], returnFirstDependency); define("swiper", [bowerPath + "/Swiper/dist/js/swiper.min", "css!" + bowerPath + "/Swiper/dist/css/swiper.min"], returnFirstDependency); - define("scroller", [embyWebComponentsBowerPath + "/scroller/smoothscroller"], returnFirstDependency); - define("toast", [embyWebComponentsBowerPath + "/toast/toast"], returnFirstDependency); - define("scrollHelper", [embyWebComponentsBowerPath + "/scrollhelper"], returnFirstDependency); - define("touchHelper", [embyWebComponentsBowerPath + "/touchhelper"], returnFirstDependency); - define("appSettings", [embyWebComponentsBowerPath + "/appsettings"], returnFirstDependency); - define("userSettings", [embyWebComponentsBowerPath + "/usersettings/usersettings"], returnFirstDependency); - define("userSettingsBuilder", [embyWebComponentsBowerPath + "/usersettings/usersettingsbuilder", "layoutManager", "browser"], getSettingsBuilder); - define("material-icons", ["css!" + embyWebComponentsBowerPath + "/fonts/material-icons/style"], returnFirstDependency); - define("systemFontsCss", ["css!" + embyWebComponentsBowerPath + "/fonts/fonts"], returnFirstDependency); - define("systemFontsSizedCss", ["css!" + embyWebComponentsBowerPath + "/fonts/fonts.sized"], returnFirstDependency); - define("scrollStyles", ["css!" + embyWebComponentsBowerPath + "/scrollstyles"], returnFirstDependency); - define("imageUploader", [embyWebComponentsBowerPath + "/imageuploader/imageuploader"], returnFirstDependency); + define("scroller", [componentsPath + "/scroller/smoothscroller"], returnFirstDependency); + define("toast", [componentsPath + "/toast/toast"], returnFirstDependency); + define("scrollHelper", [componentsPath + "/scrollhelper"], returnFirstDependency); + define("touchHelper", [componentsPath + "/touchhelper"], returnFirstDependency); + define("appSettings", [componentsPath + "/appsettings"], returnFirstDependency); + define("userSettings", [componentsPath + "/usersettings/usersettings"], returnFirstDependency); + define("userSettingsBuilder", [componentsPath + "/usersettings/usersettingsbuilder", "layoutManager", "browser"], getSettingsBuilder); + define("material-icons", ["css!" + componentsPath + "/fonts/material-icons/style"], returnFirstDependency); + define("systemFontsCss", ["css!" + componentsPath + "/fonts/fonts"], returnFirstDependency); + define("systemFontsSizedCss", ["css!" + componentsPath + "/fonts/fonts.sized"], returnFirstDependency); + define("scrollStyles", ["css!" + componentsPath + "/scrollstyles"], returnFirstDependency); + define("imageUploader", [componentsPath + "/imageuploader/imageuploader"], returnFirstDependency); define("navdrawer", ["components/navdrawer/navdrawer"], returnFirstDependency); - define("htmlMediaHelper", [embyWebComponentsBowerPath + "/htmlvideoplayer/htmlmediahelper"], returnFirstDependency); - define("viewcontainer", ["components/viewcontainer-lite", "css!" + embyWebComponentsBowerPath + "/viewmanager/viewcontainer-lite"], returnFirstDependency); + define("htmlMediaHelper", [componentsPath + "/htmlvideoplayer/htmlmediahelper"], returnFirstDependency); + define("viewcontainer", ["components/viewcontainer-lite", "css!" + componentsPath + "/viewmanager/viewcontainer-lite"], returnFirstDependency); define("queryString", [bowerPath + "/query-string/index"], function () { return queryString; }); @@ -1522,12 +1522,12 @@ var AppInfo = {}; return jQuery; }); define("fnchecked", ["legacy/fnchecked"], returnFirstDependency); - define("dialogHelper", [embyWebComponentsBowerPath + "/dialoghelper/dialoghelper"], returnFirstDependency); + define("dialogHelper", [componentsPath + "/dialoghelper/dialoghelper"], returnFirstDependency); define("inputmanager", ["inputManager"], returnFirstDependency); - define("serverNotifications", [embyWebComponentsBowerPath + "/apiInput/apiInput"], returnFirstDependency); + define("serverNotifications", [componentsPath + "/apiInput/apiInput"], returnFirstDependency); define("headroom-window", ["headroom"], createWindowHeadroom); define("appFooter-shared", ["appFooter"], createSharedAppFooter); - define("skinManager", [embyWebComponentsBowerPath + "/skinmanager"], function (skinManager) { + define("skinManager", [componentsPath + "/skinmanager"], function (skinManager) { skinManager.loadUserSkin = function (options) { require(["appRouter"], function (appRouter) { options = options || {}; @@ -1592,7 +1592,7 @@ var AppInfo = {}; return window.ApiClient; }; }); - define("appRouter", [embyWebComponentsBowerPath + "/router", "itemHelper"], function (appRouter, itemHelper) { + define("appRouter", [componentsPath + "/router", "itemHelper"], function (appRouter, itemHelper) { function showItem(item, serverId, options) { if ("string" == typeof item) { require(["connectionManager"], function (connectionManager) { From ceafa313cd31e2c39afcf6fd140d53ea699dac5f Mon Sep 17 00:00:00 2001 From: lostmypillow <47119111+lostmypillow@users.noreply.github.com> Date: Tue, 12 Mar 2019 23:13:41 -0500 Subject: [PATCH 077/220] Remove unused localization strings Improved version of original PR --- src/strings/en-us.json | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 5ac13f0aad..1502f6e6fe 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -38,7 +38,6 @@ "AlwaysPlaySubtitles": "Always play subtitles", "AlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.", "AnamorphicVideoNotSupported": "Anamorphic video not supported", - "AndroidUnlockRestoreHelp": "To restore your previous purchase, please ensure you're signed into the device with the same Google (or Amazon) account that originally made the purchase. Make sure the app store is enabled and not restricted by any parental controls, and ensure you have an active internet connection. You'll only have to do this once to restore your previous purchase.", "AnyLanguage": "Any language", "Anytime": "Anytime", "AroundTime": "Around {0}", @@ -152,7 +151,6 @@ "ButtonPrivacyPolicy": "Privacy policy", "ButtonProfile": "Profile", "ButtonProfileHelp": "Set your profile image and password.", - "ButtonPurchase": "Purchase", "ButtonQuality": "Quality", "ButtonQuickStartGuide": "Quick Start Guide", "ButtonRecord": "Record", @@ -173,7 +171,6 @@ "ButtonResetTuner": "Reset tuner", "ButtonRestart": "Restart", "ButtonRestartNow": "Restart Now", - "ButtonRestorePreviousPurchase": "Restore Purchase", "ButtonResume": "Resume", "ButtonRevoke": "Revoke", "ButtonSave": "Save", @@ -208,8 +205,6 @@ "ButtonTrailer": "Trailer", "ButtonTryAgain": "Try Again", "ButtonUninstall": "Uninstall", - "ButtonUnlockPrice": "Unlock {0}", - "ButtonUnlockWithPurchase": "Unlock with Purchase", "ButtonUnmute": "Unmute", "ButtonUp": "Up", "ButtonUpdateNow": "Update Now", @@ -319,7 +314,6 @@ "DrmChannelsNotImported": "Channels with DRM will not be imported.", "DropShadow": "Drop shadow", "DvrFeatureDescription": "Schedule individual Live TV recordings, series recordings, and more with Jellyfin DVR.", - "DvrSubscriptionRequired": "Jellyfin DVR requires an active Jellyfin Premiere subscription.", "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Jellyfin apps, and can also be used for easy in-network sign in.", "Edit": "Edit", "EditImages": "Edit images", @@ -369,7 +363,6 @@ "ErrorReachingJellyfinConnect": "There was an error reaching the Jellyfin Connect server. Please ensure you have an active internet connection and try again.", "ErrorRemovingJellyfinConnectAccount": "There was an error removing the Jellyfin Connect account. Please ensure you have an active internet connection and try again.", "ErrorSavingTvProvider": "There was an error saving the TV provider. Please ensure it is accessible and try again.", - "ErrorValidatingSupporterInfo": "There was an error validating your Jellyfin Premiere information. Please try again later.", "EveryNDays": "Every {0} days", "ExitFullscreen": "Exit full screen", "ExtraLarge": "Extra large", @@ -379,7 +372,6 @@ "FastForward": "Fast-forward", "Favorite": "Favorite", "Favorites": "Favorites", - "FeatureRequiresJellyfinPremiere": "This feature requires an active Jellyfin Premiere subscription.", "Features": "Features", "File": "File", "FileNotFound": "File not found.", @@ -441,7 +433,6 @@ "HeaderAlert": "Alert", "HeaderAllRecordings": "All Recordings", "HeaderAllowMediaDeletionFrom": "Allow Media Deletion From", - "HeaderAlreadyPaid": "Already Paid?", "HeaderApiKey": "Api Key", "HeaderApiKeys": "Api Keys", "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Jellyfin Server. Keys are issued by logging in with an Jellyfin account, or by manually granting the application a key.", @@ -456,8 +447,6 @@ "HeaderAvailableServices": "Available Services", "HeaderAwardsAndReviews": "Awards and Reviews", "HeaderBackdrops": "Backdrops", - "HeaderBecomeProjectSupporter": "Get Jellyfin Premiere", - "HeaderBenefitsJellyfinPremiere": "Benefits of Jellyfin Premiere", "HeaderBlockItemsWithNoRating": "Block items with no or unrecognized rating information:", "HeaderBooks": "Books", "HeaderBranding": "Branding", @@ -771,12 +760,9 @@ "HeaderSupportTheTeam": "Support the Jellyfin Team", "HeaderSync": "Sync", "HeaderSyncJobInfo": "Sync Job", - "HeaderSyncRequiresSub": "Downloading requires an active Jellyfin Premiere subscription.", - "HeaderSystemDlnaProfiles": "System Profiles", "HeaderTV": "TV", "HeaderTags": "Tags", "HeaderTaskTriggers": "Task Triggers", - "HeaderTermsOfPurchase": "Terms of Purchase", "HeaderTermsOfService": "Jellyfin Terms of Service", "HeaderThemeSongs": "Theme Songs", "HeaderThemeVideos": "Theme Videos", @@ -830,12 +816,9 @@ "HideWatchedContentFromLatestMedia": "Hide watched content from latest media", "Home": "Home", "Horizontal": "Horizontal", - "HowDidYouPay": "How did you pay?", "HowToConnectFromJellyfinApps": "How to Connect from Jellyfin apps", "HowWouldYouLikeToAddUser": "How would you like to add a user?", "HttpsRequiresCert": "To enable secure connections, you will need to supply a trusted SSL certificate, such as Lets Encrypt. Please either supply a certificate, or disable secure connections.", - "IHaveJellyfinPremiere": "I have Jellyfin Premiere", - "IPurchasedThisApp": "I purchased this app", "Identify": "Identify", "ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG/PNG only.", "Images": "Images", @@ -1355,7 +1338,6 @@ "LinkApi": "Api", "LinkCommunity": "Community", "LinkGithub": "Github", - "LinkLearnMoreAboutSubscription": "Learn about Jellyfin Premiere", "LinksValue": "Links: {0}", "List": "List", "Live": "Live", @@ -1436,7 +1418,6 @@ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Jellyfin Server will be abruptly terminated.", "MessageConfirmShutdown": "Are you sure you wish to shutdown Jellyfin Server?", "MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?", - "MessageConfirmSubCancel": "NO, Please don't go... You will miss out on all the great features of Jellyfin Premiere!", "MessageConnectAccountRequiredToInviteGuest": "In order to invite guests you need to first link your Jellyfin account to this server.", "MessageContactAdminToResetPassword": "Please contact your system administrator to reset your password.", "MessageCreateAccountAt": "Create an account at {0}", @@ -1448,9 +1429,7 @@ "MessageDownloadQueued": "Download queued.", "MessageEnablingOptionLongerScans": "Enabling this option may result in significantly longer library scans.", "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.", - "MessageErrorLoadingSupporterInfo": "There was an error loading Jellyfin Premiere information. Please try again later.", "MessageErrorPlayingVideo": "There was an error playing the video.", - "MessageFeatureIncludedWithSupporter": "You are registered for this feature, and will be able to continue using it with an active Jellyfin Premiere subscription.", "MessageFileNotFound": "File not found.", "MessageFileReadError": "There was an error reading the file. Please try again.", "MessageFileWillBeDeleted": "The following file will be deleted:", @@ -1487,7 +1466,6 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "MessageNothingHere": "Nothing here.", "MessagePasswordResetForUsers": "Passwords have been removed for the following users. To login, sign in with a blank password.", - "MessagePaymentServicesUnavailable": "Payment services are currently unavailable. Please try again later.", "MessagePendingJellyfinAccountAdded": "The Jellyfin account has been added to this user. An email will be sent to the owner of the account. The invitation will need to be confirmed by clicking a link within the email.", "MessagePlayAccessRestricted": "Playback of this content is currently restricted. Please contact your Jellyfin Server administrator for more information.", "MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.", @@ -1496,8 +1474,6 @@ "MessagePleaseWait": "Please wait. This may take a minute.", "MessagePluginConfigurationRequiresLocalAccess": "To configure this plugin please sign in to your local server directly.", "MessagePluginInstallDisclaimer": "Plugins built by Jellyfin community members are a great way to enhance your Jellyfin experience with additional features and benefits. Before installing, please be aware of the effects they may have on your Jellyfin Server, such as longer library scans, additional background processing, and decreased system stability.", - "MessagePluginRequiresSubscription": "This plugin will require an active Jellyfin Premiere subscription after the 14 day free trial.", - "MessagePremiumPluginRequiresMembership": "This plugin will require an active Jellyfin Premiere subscription in order to purchase after the 14 day free trial.", "MessageReenableUser": "See below to reenable", "MessageServerConfigurationUpdated": "Server configuration has been updated", "MessageSettingsSaved": "Settings saved.", @@ -1505,13 +1481,8 @@ "MessageThankYouForConnectSignUpNoValidation": "Thank you for signing up for Jellyfin Connect! You will now be asked to login with your Jellyfin Connect information.", "MessageThankYouForSupporting": "Thank you for supporting Jellyfin.", "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your Jellyfin library:", - "MessageToValidateSupporter": "If you have an active Jellyfin Premiere subscription, ensure you've setup Jellyfin Premiere in your Jellyfin Server Dashboard, which you can access by clicking Jellyfin Premiere within the main menu.", - "MessageTrialExpired": "The trial period for this feature has expired", - "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", "MessageTunerDeviceNotListed": "Is your tuner device not listed? Try installing an external service provider for more Live TV options.", "MessageUnableToConnectToServer": "We're unable to connect to the selected server right now. Please ensure it is running and try again.", - "MessageUnlockAppWithPurchaseOrSupporter": "Unlock this feature with a small one-time purchase, or with an active Jellyfin Premiere subscription.", - "MessageUnlockAppWithSupporter": "Unlock this feature with an active Jellyfin Premiere subscription.", "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders.", "MessageWeDidntRecognizeCommand": "We're sorry, we didn't recognize that command.", "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", @@ -2137,7 +2108,6 @@ "TermsOfUse": "Terms of use", "TextConnectToServerManually": "Connect to server manually", "TextEnjoyBonusFeatures": "Enjoy Bonus Features", - "ThankYouForTryingEnjoyOneMinute": "Please enjoy one minute of playback. Thank you for trying Jellyfin.", "ThemeSongs": "Theme songs", "ThemeVideos": "Theme videos", "Themes": "Themes", @@ -2213,7 +2183,6 @@ "ValueOneTrailer": "1 trailer", "ValuePremiered": "Premiered {0}", "ValuePremieres": "Premieres {0}", - "ValuePriceUSD": "Price: {0} (USD)", "ValueSeconds": "{0} seconds", "ValueSeriesCount": "{0} series", "ValueSeriesYearToPresent": "{0} - Present", @@ -2265,4 +2234,4 @@ "XmlTvSportsCategoriesHelp": "Programs with these categories will be displayed as sports programs. Separate multiple with '|'.", "Yes": "Yes", "Yesterday": "Yesterday" -} \ No newline at end of file +} From 8234f189a0cd3047aa551cc1e3630851a74af4ce Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Tue, 12 Mar 2019 22:49:13 +0000 Subject: [PATCH 078/220] fix bug apphost naming resolution --- src/scripts/site.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index b2d17265c8..caae156ba5 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1200,7 +1200,7 @@ var AppInfo = {}; console.log("Begin onAppReady"); // ensure that appHost is loaded in this point - require(['appHost'], function (appHost) { + require(['apphost'], function (appHost) { var isInBackground = -1 !== self.location.href.toString().toLowerCase().indexOf("start=backgroundsync"); window.Emby = {}; From 70d66f64550f7457346552c40ef83420d63945ba Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Wed, 13 Mar 2019 23:22:17 +0000 Subject: [PATCH 079/220] remove unecessary var for onwebcomponentsready --- src/scripts/site.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index fc24fe3b2e..a47797ff3f 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1293,7 +1293,6 @@ var AppInfo = {}; } if (!window.Promise || browser.web0s) { - initialDependencies.push(); require(["components/native-promise-only/lib/npo.src"], init); } else { init(); From f698ba1f39ab183dab4c68008b9c8392751e39a3 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Wed, 13 Mar 2019 21:34:58 -0400 Subject: [PATCH 080/220] Correct syntax error in networkPath --- src/dashboard/dashboardgeneral.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dashboard/dashboardgeneral.js b/src/dashboard/dashboardgeneral.js index c0ff217ffe..ed3b000b12 100644 --- a/src/dashboard/dashboardgeneral.js +++ b/src/dashboard/dashboardgeneral.js @@ -97,7 +97,7 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb $("#txtMetadataPath", view).val(path); } if (networkPath) { - $("#txtMetadataNetworkPath", view).val(networkPath)); + $("#txtMetadataNetworkPath", view).val(networkPath); } picker.close(); }, From ca9e5d83bfb71c8eb77cfc1e3faaed31e645b66d Mon Sep 17 00:00:00 2001 From: dkanada Date: Thu, 14 Mar 2019 00:05:45 -0700 Subject: [PATCH 081/220] remove write check and add warning to the description --- src/dashboard/dashboardgeneral.js | 1 - src/strings/en-us.json | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/dashboard/dashboardgeneral.js b/src/dashboard/dashboardgeneral.js index 6ef1c4d221..7ecd7cb1c9 100644 --- a/src/dashboard/dashboardgeneral.js +++ b/src/dashboard/dashboardgeneral.js @@ -119,7 +119,6 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb } picker.close(); }, - validateWriteable: true, header: Globalize.translate("LabelWebPath"), instruction: Globalize.translate("LabelWebPathHelp") }) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 6fe64cdf4a..dca0c0797e 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -1123,7 +1123,7 @@ "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata.", "LabelWebPath": "Web path:", - "LabelWebPathHelp": "The path where the web client source is located.", + "LabelWebPathHelp": "The path where the web client source is located. Do not change this unless you plan on moving the web files, or the web interface will break.", "LabelMetadataReaders": "Metadata readers:", "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.", "LabelMetadataSavers": "Metadata savers:", @@ -2268,4 +2268,4 @@ "XmlTvSportsCategoriesHelp": "Programs with these categories will be displayed as sports programs. Separate multiple with '|'.", "Yes": "Yes", "Yesterday": "Yesterday" -} \ No newline at end of file +} From f95018e80978b1501027f19e4e2c831ce086905e Mon Sep 17 00:00:00 2001 From: lostmypillow <47119111+lostmypillow@users.noreply.github.com> Date: Thu, 14 Mar 2019 16:11:52 -0500 Subject: [PATCH 082/220] Added back DLNA string --- src/strings/en-us.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 1502f6e6fe..9c0cac2a24 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -760,6 +760,7 @@ "HeaderSupportTheTeam": "Support the Jellyfin Team", "HeaderSync": "Sync", "HeaderSyncJobInfo": "Sync Job", + "HeaderSystemDlnaProfiles": "System Profiles", "HeaderTV": "TV", "HeaderTags": "Tags", "HeaderTaskTriggers": "Task Triggers", From 9dde221c073e69782da0d39e4d2cefde6d0933b3 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Thu, 14 Mar 2019 23:40:56 +0000 Subject: [PATCH 083/220] remove forced volumeosd load for edge --- src/scripts/site.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index a47797ff3f..3d3c986aeb 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1224,7 +1224,7 @@ var AppInfo = {}; require(["playerSelectionMenu", "components/playback/remotecontrolautoplay"]); } - if (!(appHost.supports("physicalvolumecontrol") && !browser.touch || browser.edge)) { + if (!appHost.supports("physicalvolumecontrol") || browser.touch) { require(["components/playback/volumeosd"]); } From 8d3027d10075957854e39b475077b36a00af024d Mon Sep 17 00:00:00 2001 From: Phallacy Date: Sat, 16 Mar 2019 00:18:17 -0700 Subject: [PATCH 084/220] added settings to support configurable lockout --- src/scripts/useredit.js | 4 ++-- src/strings/en-us.json | 3 +++ src/useredit.html | 7 +++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/scripts/useredit.js b/src/scripts/useredit.js index 709b2557c1..62c9ed37c6 100644 --- a/src/scripts/useredit.js +++ b/src/scripts/useredit.js @@ -28,7 +28,7 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, l IsHidden: !1 })).then(function(folders) { loadDeleteFolders(page, user, folders.Items) - }), user.Policy.IsDisabled ? $(".disabledUserBanner", page).show() : $(".disabledUserBanner", page).hide(), "Guest" == user.ConnectLinkType ? ($("#fldConnectInfo", page).hide(), $("#txtUserName", page).prop("disabled", "disabled")) : ($("#txtUserName", page).prop("disabled", "").removeAttr("disabled"), $("#fldConnectInfo", page).show()), $(".lnkEditUserPreferences", page).attr("href", "mypreferencesmenu.html?userId=" + user.Id), libraryMenu.setTitle(user.Name), page.querySelector(".username").innerHTML = user.Name, $("#txtUserName", page).val(user.Name), $("#chkIsAdmin", page).checked(user.Policy.IsAdministrator), $("#chkDisabled", page).checked(user.Policy.IsDisabled), $("#chkIsHidden", page).checked(user.Policy.IsHidden), $("#chkRemoteControlSharedDevices", page).checked(user.Policy.EnableSharedDeviceControl), $("#chkEnableRemoteControlOtherUsers", page).checked(user.Policy.EnableRemoteControlOfOtherUsers), $("#chkEnableDownloading", page).checked(user.Policy.EnableContentDownloading), $("#chkManageLiveTv", page).checked(user.Policy.EnableLiveTvManagement), $("#chkEnableLiveTvAccess", page).checked(user.Policy.EnableLiveTvAccess), $("#chkEnableMediaPlayback", page).checked(user.Policy.EnableMediaPlayback), $("#chkEnableAudioPlaybackTranscoding", page).checked(user.Policy.EnableAudioPlaybackTranscoding), $("#chkEnableVideoPlaybackTranscoding", page).checked(user.Policy.EnableVideoPlaybackTranscoding), $("#chkEnableVideoPlaybackRemuxing", page).checked(user.Policy.EnablePlaybackRemuxing), $("#chkRemoteAccess", page).checked(null == user.Policy.EnableRemoteAccess || user.Policy.EnableRemoteAccess), $("#chkEnableSyncTranscoding", page).checked(user.Policy.EnableSyncTranscoding), $("#chkEnableConversion", page).checked(user.Policy.EnableMediaConversion || !1), $("#chkEnableSharing", page).checked(user.Policy.EnablePublicSharing), $("#txtRemoteClientBitrateLimit", page).val(user.Policy.RemoteClientBitrateLimit / 1e6 || ""), loading.hide() + }), user.Policy.IsDisabled ? $(".disabledUserBanner", page).show() : $(".disabledUserBanner", page).hide(), "Guest" == user.ConnectLinkType ? ($("#fldConnectInfo", page).hide(), $("#txtUserName", page).prop("disabled", "disabled")) : ($("#txtUserName", page).prop("disabled", "").removeAttr("disabled"), $("#fldConnectInfo", page).show()), $(".lnkEditUserPreferences", page).attr("href", "mypreferencesmenu.html?userId=" + user.Id), libraryMenu.setTitle(user.Name), page.querySelector(".username").innerHTML = user.Name, $("#txtUserName", page).val(user.Name), $("#chkIsAdmin", page).checked(user.Policy.IsAdministrator), $("#chkDisabled", page).checked(user.Policy.IsDisabled), $("#chkIsHidden", page).checked(user.Policy.IsHidden), $("#chkRemoteControlSharedDevices", page).checked(user.Policy.EnableSharedDeviceControl), $("#chkEnableRemoteControlOtherUsers", page).checked(user.Policy.EnableRemoteControlOfOtherUsers), $("#chkEnableDownloading", page).checked(user.Policy.EnableContentDownloading), $("#chkManageLiveTv", page).checked(user.Policy.EnableLiveTvManagement), $("#chkEnableLiveTvAccess", page).checked(user.Policy.EnableLiveTvAccess), $("#chkEnableMediaPlayback", page).checked(user.Policy.EnableMediaPlayback), $("#chkEnableAudioPlaybackTranscoding", page).checked(user.Policy.EnableAudioPlaybackTranscoding), $("#chkEnableVideoPlaybackTranscoding", page).checked(user.Policy.EnableVideoPlaybackTranscoding), $("#chkEnableVideoPlaybackRemuxing", page).checked(user.Policy.EnablePlaybackRemuxing), $("#chkRemoteAccess", page).checked(null == user.Policy.EnableRemoteAccess || user.Policy.EnableRemoteAccess), $("#chkEnableSyncTranscoding", page).checked(user.Policy.EnableSyncTranscoding), $("#chkEnableConversion", page).checked(user.Policy.EnableMediaConversion || !1), $("#chkEnableSharing", page).checked(user.Policy.EnablePublicSharing), $("#txtRemoteClientBitrateLimit", page).val(user.Policy.RemoteClientBitrateLimit / 1e6 || ""), $("#txtLoginAttemptsBeforeLockout", page).val(user.Policy.LoginAttemptsBeforeLockout || "0"), loading.hide() } function onSaveComplete(page, user) { @@ -40,7 +40,7 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, l } function saveUser(user, page) { - user.Name = $("#txtUserName", page).val(), user.Policy.IsAdministrator = $("#chkIsAdmin", page).checked(), user.Policy.IsHidden = $("#chkIsHidden", page).checked(), user.Policy.IsDisabled = $("#chkDisabled", page).checked(), user.Policy.EnableRemoteControlOfOtherUsers = $("#chkEnableRemoteControlOtherUsers", page).checked(), user.Policy.EnableLiveTvManagement = $("#chkManageLiveTv", page).checked(), user.Policy.EnableLiveTvAccess = $("#chkEnableLiveTvAccess", page).checked(), user.Policy.EnableSharedDeviceControl = $("#chkRemoteControlSharedDevices", page).checked(), user.Policy.EnableMediaPlayback = $("#chkEnableMediaPlayback", page).checked(), user.Policy.EnableAudioPlaybackTranscoding = $("#chkEnableAudioPlaybackTranscoding", page).checked(), user.Policy.EnableVideoPlaybackTranscoding = $("#chkEnableVideoPlaybackTranscoding", page).checked(), user.Policy.EnablePlaybackRemuxing = $("#chkEnableVideoPlaybackRemuxing", page).checked(), user.Policy.EnableContentDownloading = $("#chkEnableDownloading", page).checked(), user.Policy.EnableSyncTranscoding = $("#chkEnableSyncTranscoding", page).checked(), user.Policy.EnableMediaConversion = $("#chkEnableConversion", page).checked(), user.Policy.EnablePublicSharing = $("#chkEnableSharing", page).checked(), user.Policy.EnableRemoteAccess = $("#chkRemoteAccess", page).checked(), user.Policy.RemoteClientBitrateLimit = parseInt(1e6 * parseFloat($("#txtRemoteClientBitrateLimit", page).val() || "0")), user.Policy.AuthenticationProviderId = page.querySelector(".selectLoginProvider").value, user.Policy.EnableContentDeletion = $("#chkEnableDeleteAllFolders", page).checked(), user.Policy.EnableContentDeletionFromFolders = user.Policy.EnableContentDeletion ? [] : $(".chkFolder", page).get().filter(function(c) { + user.Name = $("#txtUserName", page).val(), user.Policy.IsAdministrator = $("#chkIsAdmin", page).checked(), user.Policy.IsHidden = $("#chkIsHidden", page).checked(), user.Policy.IsDisabled = $("#chkDisabled", page).checked(), user.Policy.EnableRemoteControlOfOtherUsers = $("#chkEnableRemoteControlOtherUsers", page).checked(), user.Policy.EnableLiveTvManagement = $("#chkManageLiveTv", page).checked(), user.Policy.EnableLiveTvAccess = $("#chkEnableLiveTvAccess", page).checked(), user.Policy.EnableSharedDeviceControl = $("#chkRemoteControlSharedDevices", page).checked(), user.Policy.EnableMediaPlayback = $("#chkEnableMediaPlayback", page).checked(), user.Policy.EnableAudioPlaybackTranscoding = $("#chkEnableAudioPlaybackTranscoding", page).checked(), user.Policy.EnableVideoPlaybackTranscoding = $("#chkEnableVideoPlaybackTranscoding", page).checked(), user.Policy.EnablePlaybackRemuxing = $("#chkEnableVideoPlaybackRemuxing", page).checked(), user.Policy.EnableContentDownloading = $("#chkEnableDownloading", page).checked(), user.Policy.EnableSyncTranscoding = $("#chkEnableSyncTranscoding", page).checked(), user.Policy.EnableMediaConversion = $("#chkEnableConversion", page).checked(), user.Policy.EnablePublicSharing = $("#chkEnableSharing", page).checked(), user.Policy.EnableRemoteAccess = $("#chkRemoteAccess", page).checked(), user.Policy.RemoteClientBitrateLimit = parseInt(1e6 * parseFloat($("#txtRemoteClientBitrateLimit", page).val() || "0")), user.Policy.LoginAttemptsBeforeLockout = parseInt($("#txtLoginAttemptsBeforeLockout", page).val() || "0"), user.Policy.AuthenticationProviderId = page.querySelector(".selectLoginProvider").value, user.Policy.EnableContentDeletion = $("#chkEnableDeleteAllFolders", page).checked(), user.Policy.EnableContentDeletionFromFolders = user.Policy.EnableContentDeletion ? [] : $(".chkFolder", page).get().filter(function(c) { return c.checked }).map(function(c) { return c.getAttribute("data-id") diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 9c0cac2a24..5e5e43f90b 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -1300,6 +1300,7 @@ "LabelUserAgent": "User agent:", "LabelUserLibrary": "User library:", "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.", + "LabelUserLoginAttemptsBeforeLockout": "Failed Logins before Lockout:", "LabelUserRemoteClientBitrateLimitHelp": "This will override the default global value set in server playback settings.", "LabelUsername": "Username:", "LabelVaapiDevice": "VA API Device:", @@ -1696,6 +1697,8 @@ "OptionLikes": "Likes", "OptionList": "List", "OptionLocked": "Locked", + "OptionLoginAttemptsBeforeLockout": "Determines how many incorrect password attempts can be made before lockout occurs.", + "OptionLoginAttemptsBeforeLockoutHelp":"0 inherits the old default of 3 for non admin and 5 for admin, -1 to disable lockout", "OptionLogo": "Logo", "OptionMax": "Max", "OptionMenu": "Menu", diff --git a/src/useredit.html b/src/useredit.html index 7a7fcd990c..ba1b054081 100644 --- a/src/useredit.html +++ b/src/useredit.html @@ -154,6 +154,13 @@
${OptionDisableUserHelp}
+
+ +
${OptionLoginAttemptsBeforeLockoutHelp}
+
${OptionDisableUserHelp}
-
- -
${OptionLoginAttemptsBeforeLockoutHelp}
-
${OptionHideUserFromLoginHelp}
+
+
+ +
${OptionLoginAttemptsBeforeLockout}
+
${OptionLoginAttemptsBeforeLockoutHelp}
+
+

+
- +
${OptionLoginAttemptsBeforeLockout}
${OptionLoginAttemptsBeforeLockoutHelp}
From e38a34384a2933f2b3dab3f176c88f3e8d39d11f Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 16 Mar 2019 01:55:47 -0700 Subject: [PATCH 087/220] add ci for eslint --- .drone.yml | 9 +++++++++ .eslintrc.yml | 3 +++ run-eslint.sh | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 .drone.yml create mode 100644 .eslintrc.yml create mode 100644 run-eslint.sh diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000000..d1a67db6e8 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,9 @@ +--- +kind: pipeline +name: eslint + +steps: +- name: run + image: nextcloudci/eslint:eslint-1 + commands: + - ./run-eslint.sh diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 0000000000..943b958ecd --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,3 @@ +env: + browser: true + amd: true diff --git a/run-eslint.sh b/run-eslint.sh new file mode 100644 index 0000000000..46b74c1a7e --- /dev/null +++ b/run-eslint.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +set -e + +# used this pull request for reference +# https://github.com/nextcloud/spreed/pull/48 +ESLINT=$(which eslint || true) +if [ -z "$ESLINT" ] +then + echo "could not find eslint in $PATH" + exit 1 +fi + +echo checking scripts with $ESLINT +find -name "*.js" -print0 | xargs -0 $ESLINT + +# use this line to test changes locally +#find src -name "*.js" -exec sh -c 'npx eslint $1' -- {} \; From 9e38eeeb16eb99a3b969d2e46c4b559a8ee852a7 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 16:50:51 +0000 Subject: [PATCH 088/220] removing nativedirectorychooser require --- src/scripts/site.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 3d3c986aeb..2a2f8a6980 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -538,10 +538,6 @@ var AppInfo = {}; } function init() { - if ("android" === self.appMode) { - define("nativedirectorychooser", ["cordova/nativedirectorychooser"], returnFirstDependency); - } - define("livetvcss", ["css!css/livetv.css"], returnFirstDependency); define("detailtablecss", ["css!css/detailtable.css"], returnFirstDependency); define("buttonenabled", ["legacy/buttonenabled"], returnFirstDependency); From c2d35ee599eff085b8d01815db6fb9018132c2ee Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 16:52:41 +0000 Subject: [PATCH 089/220] removing require for module file upload --- src/scripts/site.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 2a2f8a6980..193f616b05 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1475,13 +1475,6 @@ var AppInfo = {}; define("filterMenu", [componentsPath + "/filtermenu/filtermenu"], returnFirstDependency); define("sortMenu", [componentsPath + "/sortmenu/sortmenu"], returnFirstDependency); define("registrationServices", [componentsPath + "/registrationservices/registrationservices"], returnFirstDependency); - - if ("cordova" === self.appMode || "android" === self.appMode) { - define("fileupload", ["cordova/fileupload"], returnFirstDependency); - } else { - define("fileupload", [apiClientBowerPath + "/fileupload"], returnFirstDependency); - } - define("connectionmanager", [apiClientBowerPath + "/connectionmanager"]); define("serversync", [apiClientBowerPath + "/sync/serversync"], returnFirstDependency); define("multiserversync", [apiClientBowerPath + "/sync/multiserversync"], returnFirstDependency); From c391eaf5453d99a4980f55ea759cf57d38c2a54d Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 16:52:49 +0000 Subject: [PATCH 090/220] removing module fileupload --- src/bower_components/emby-apiclient/fileupload.js | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 src/bower_components/emby-apiclient/fileupload.js diff --git a/src/bower_components/emby-apiclient/fileupload.js b/src/bower_components/emby-apiclient/fileupload.js deleted file mode 100644 index 91f77395e6..0000000000 --- a/src/bower_components/emby-apiclient/fileupload.js +++ /dev/null @@ -1,8 +0,0 @@ -define([], function() { - "use strict"; - - function FileUpload() {} - return FileUpload.prototype.upload = function(file, url) { - return Promise.reject() - }, FileUpload -}); \ No newline at end of file From 4be8a788b08e049284a5a1910976cf078d81a917 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 17:15:37 +0000 Subject: [PATCH 091/220] assume server discovery is in NativeShell api --- .../emby-apiclient/connectionmanager.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/bower_components/emby-apiclient/connectionmanager.js b/src/bower_components/emby-apiclient/connectionmanager.js index 39824d31f7..93e9673a46 100644 --- a/src/bower_components/emby-apiclient/connectionmanager.js +++ b/src/bower_components/emby-apiclient/connectionmanager.js @@ -269,12 +269,15 @@ define(["events", "apiclient", "appStorage"], function(events, apiClientFactory, }); resolve(servers) }; - require(["serverdiscovery"], function(serverDiscovery) { - serverDiscovery.findServers(1e3).then(onFinish, function() { + + if (window.NativeShell && typeof window.NativeShell.findServers === 'function') { + window.NativeShell.findServers(1e3).then(onFinish, function() { onFinish([]) - }) - }) - }) + }); + } else { + resolve([]); + } + }); } function convertEndpointAddressToManualAddress(info) { From 04480fc8eb9006ef6394a76892f37e045ab80879 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 17:15:59 +0000 Subject: [PATCH 092/220] removed serverdiscovery require --- src/scripts/site.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 193f616b05..b64686ac67 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -462,12 +462,6 @@ var AppInfo = {}; define("registerElement", [bowerPath + "/document-register-element/build/document-register-element"], returnFirstDependency); } - if ("cordova" === self.appMode || "android" === self.appMode) { - define("serverdiscovery", ["cordova/serverdiscovery"], returnFirstDependency); - } else { - define("serverdiscovery", [apiClientBowerPath + "/serverdiscovery"], returnFirstDependency); - } - if ("cordova" === self.appMode && browser.iOSVersion && browser.iOSVersion < 11) { define("imageFetcher", ["cordova/imagestore"], returnFirstDependency); } else { From 60c0e58c647a51aa5349bc4c80d50f5cbd91d1f2 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 17:16:11 +0000 Subject: [PATCH 093/220] removed serverdiscovery module --- src/bower_components/emby-apiclient/serverdiscovery.js | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 src/bower_components/emby-apiclient/serverdiscovery.js diff --git a/src/bower_components/emby-apiclient/serverdiscovery.js b/src/bower_components/emby-apiclient/serverdiscovery.js deleted file mode 100644 index 4f18505ecc..0000000000 --- a/src/bower_components/emby-apiclient/serverdiscovery.js +++ /dev/null @@ -1,8 +0,0 @@ -define([], function() { - "use strict"; - return { - findServers: function(timeoutMs) { - return Promise.resolve([]) - } - } -}); \ No newline at end of file From bd17f0670806d923f9669e6b6ee4f5c2981191bc Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 17:51:24 +0000 Subject: [PATCH 094/220] fix require apiInput to serverNotifications --- src/scripts/site.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 3d3c986aeb..e1d91ee99c 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1232,7 +1232,7 @@ var AppInfo = {}; require(["mediaSession"]); } - require(["apiInput"]); + require(["serverNotifications"]); if (!browser.tv && !browser.xboxOne) { require(["components/playback/playbackorientation"]); From 3de82f210af7c08123af70bdb2f48fa3d4da324a Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 18:11:46 +0000 Subject: [PATCH 095/220] using NativeShell api for native apps in shell.js --- src/components/shell.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/components/shell.js b/src/components/shell.js index 0083404e19..762039ac42 100644 --- a/src/components/shell.js +++ b/src/components/shell.js @@ -2,8 +2,13 @@ define([], function () { 'use strict'; return { - openUrl: function (url) { - window.open(url, '_blank'); + openUrl: function (url, target) { + if (window.NativeShell) { + window.NativeShell.openUrl(url, target); + } else { + window.open(url, target || '_blank'); + } + }, canExec: false, exec: function (options) { @@ -12,10 +17,14 @@ define([], function () { return Promise.reject(); }, enableFullscreen: function () { - // do nothing since this is for native apps + if (window.NativeShell) { + window.NativeShell.enableFullscreen(); + } }, disableFullscreen: function () { - // do nothing since this is for native apps + if (window.NativeShell) { + window.NativeShell.disableFullscreen(); + } } }; }); \ No newline at end of file From c22ad0f204e8adc5c670e095ab308cc42aabf14e Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 18:13:26 +0000 Subject: [PATCH 096/220] removing require for module cordova shell --- src/scripts/site.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index b64686ac67..fc7d1d1cf6 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -441,11 +441,7 @@ var AppInfo = {}; define("lazyLoader", [componentsPath + "/lazyloader/lazyloader-scroll"], returnFirstDependency); } - if ("android" === self.appMode) { - define("shell", ["cordova/shell"], returnFirstDependency); - } else { - define("shell", [componentsPath + "/shell"], returnFirstDependency); - } + define("shell", [componentsPath + "/shell"], returnFirstDependency); if ("cordova" === self.appMode || "android" === self.appMode) { define("apiclientcore", ["bower_components/emby-apiclient/apiclient"], returnFirstDependency); @@ -1222,7 +1218,7 @@ var AppInfo = {}; require(["mediaSession"]); } - require(["apiInput"]); + require(["serverNotifications"]); if (!browser.tv && !browser.xboxOne) { require(["components/playback/playbackorientation"]); From d8d3b0b4c75a80405d69d80ad28627896e25640c Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 18:21:07 +0000 Subject: [PATCH 097/220] remove unused module wakeonlan --- src/bower_components/emby-apiclient/wakeonlan.js | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 src/bower_components/emby-apiclient/wakeonlan.js diff --git a/src/bower_components/emby-apiclient/wakeonlan.js b/src/bower_components/emby-apiclient/wakeonlan.js deleted file mode 100644 index 58c01e61a5..0000000000 --- a/src/bower_components/emby-apiclient/wakeonlan.js +++ /dev/null @@ -1,15 +0,0 @@ -define([], function() { - "use strict"; - - function send(info) { - return Promise.reject() - } - - function isSupported() { - return !1 - } - return { - send: send, - isSupported: isSupported - } -}); \ No newline at end of file From 5cc1821e1206c06c9c0158f2e6cd1c00d890f90f Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 18:26:42 +0000 Subject: [PATCH 098/220] remove require for module cordova chromecast --- src/scripts/site.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index fc7d1d1cf6..f5a4233bfb 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1126,10 +1126,6 @@ var AppInfo = {}; "components/youtubeplayer/plugin" ]; - if ("cordova" === self.appMode) { - list.push("cordova/chromecast"); - } - if ("android" === self.appMode) { list.push("cordova/externalplayer"); } From e13796e4f3d986a80a9c4369ec5e0b35dbf9d8d2 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 19:19:00 +0000 Subject: [PATCH 099/220] add NativeShell API to filesystem module --- src/components/filesystem.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/filesystem.js b/src/components/filesystem.js index 4489d2921f..e022a1c6d0 100644 --- a/src/components/filesystem.js +++ b/src/components/filesystem.js @@ -3,10 +3,14 @@ define([], function () { return { fileExists: function (path) { - return Promise.reject(); + if (window.NativeShell && window.NativeShell.FileSystem) { + return window.NativeShell.FileSystem.fileExists(path); + } }, directoryExists: function (path) { - return Promise.reject(); + if (window.NativeShell && window.NativeShell.FileSystem) { + return window.NativeShell.FileSystem.directoryExists(path); + } } }; }); \ No newline at end of file From 42beea23b6ce3a49fcd2a08c41c3f6fcf4961616 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 19:19:24 +0000 Subject: [PATCH 100/220] removed require for module cordova filesystem --- src/scripts/site.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index f5a4233bfb..989d3161f9 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -429,11 +429,7 @@ var AppInfo = {}; var apiClientBowerPath = bowerPath + "/emby-apiclient"; var componentsPath = "components"; - if ("android" === self.appMode) { - define("filesystem", ["cordova/filesystem"], returnFirstDependency); - } else { - define("filesystem", [componentsPath + "/filesystem"], returnFirstDependency); - } + define("filesystem", [componentsPath + "/filesystem"], returnFirstDependency); if (window.IntersectionObserver && !browser.edge) { define("lazyLoader", [componentsPath + "/lazyloader/lazyloader-intersectionobserver"], returnFirstDependency); From e39d364874827e98523771f444831dc6006b130c Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 19:20:38 +0000 Subject: [PATCH 101/220] removed require module for cordova imagestore --- src/scripts/site.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 989d3161f9..1908b2b816 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -454,11 +454,7 @@ var AppInfo = {}; define("registerElement", [bowerPath + "/document-register-element/build/document-register-element"], returnFirstDependency); } - if ("cordova" === self.appMode && browser.iOSVersion && browser.iOSVersion < 11) { - define("imageFetcher", ["cordova/imagestore"], returnFirstDependency); - } else { - define("imageFetcher", [componentsPath + "/images/basicimagefetcher"], returnFirstDependency); - } + define("imageFetcher", [componentsPath + "/images/basicimagefetcher"], returnFirstDependency); var preferNativeAlerts = browser.tv; From a77058de6192d44f19a99013a2ed62e147d9ced8 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 19:25:46 +0000 Subject: [PATCH 102/220] added NativeShell API to localsync module --- src/bower_components/emby-apiclient/sync/localsync.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bower_components/emby-apiclient/sync/localsync.js b/src/bower_components/emby-apiclient/sync/localsync.js index cea244de08..f2f5f4e9e3 100644 --- a/src/bower_components/emby-apiclient/sync/localsync.js +++ b/src/bower_components/emby-apiclient/sync/localsync.js @@ -3,6 +3,10 @@ define(["connectionManager"], function(connectionManager) { var isSyncing; return { sync: function(options) { + if (window.NativeShell) { + return window.NativeShell.sync(options); + } + return console.log("localSync.sync starting..."), isSyncing ? Promise.resolve() : (isSyncing = !0, new Promise(function(resolve, reject) { require(["multiserversync", "appSettings"], function(MultiServerSync, appSettings) { options = options || {}, options.cameraUploadServers = appSettings.cameraUploadServers(), (new MultiServerSync).sync(connectionManager, options).then(function() { From 164bba2fafa3694dfc70524634fb282b7093b752 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 19:26:30 +0000 Subject: [PATCH 103/220] removed require for module cordova localsync --- src/scripts/site.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 1908b2b816..5683e1538c 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -512,12 +512,8 @@ var AppInfo = {}; define("filerepository", [apiClientBowerPath + "/sync/filerepository"], returnFirstDependency); } - if ("android" === self.appMode) { - define("localsync", ["cordova/localsync"], returnFirstDependency); - } else { define("localsync", [apiClientBowerPath + "/sync/localsync"], returnFirstDependency); } - } function init() { define("livetvcss", ["css!css/livetv.css"], returnFirstDependency); From 8b6b9974c79812fd9c7e0e761b66cb1309049852 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 19:34:19 +0000 Subject: [PATCH 104/220] removed require for cordova appshortcuts --- src/scripts/site.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 5683e1538c..e3bfe5c8b2 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -512,8 +512,8 @@ var AppInfo = {}; define("filerepository", [apiClientBowerPath + "/sync/filerepository"], returnFirstDependency); } - define("localsync", [apiClientBowerPath + "/sync/localsync"], returnFirstDependency); - } + define("localsync", [apiClientBowerPath + "/sync/localsync"], returnFirstDependency); + } function init() { define("livetvcss", ["css!css/livetv.css"], returnFirstDependency); @@ -1180,7 +1180,7 @@ var AppInfo = {}; if ("cordova" === self.appMode || "android" === self.appMode) { if (browser.android) { - require(["cordova/mediasession", "cordova/chromecast", "cordova/appshortcuts"]); + require(["cordova/mediasession"]); } else if (browser.safari) { require(["cordova/mediasession", "cordova/volume", "cordova/statusbar", "cordova/backgroundfetch"]); } From 856d87a9b2d1f43a0b7c9253966511f245fca236 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 21:21:40 +0000 Subject: [PATCH 105/220] clean filerepository and transfermanager requires --- src/scripts/site.js | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index e3bfe5c8b2..222717969c 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -497,21 +497,8 @@ var AppInfo = {}; define("castSenderApiLoader", [], getCastSenderApiLoader); } - if (self.Windows) { - define("bgtaskregister", ["environments/windows-uwp/bgtaskregister"], returnFirstDependency); - define("transfermanager", ["environments/windows-uwp/transfermanager"], returnFirstDependency); - define("filerepository", ["environments/windows-uwp/filerepository"], returnFirstDependency); - } else if ("cordova" === self.appMode) { - define("filerepository", ["cordova/filerepository"], returnFirstDependency); - define("transfermanager", ["filerepository"], returnFirstDependency); - } else if ("android" === self.appMode) { - define("transfermanager", ["cordova/transfermanager"], returnFirstDependency); - define("filerepository", ["cordova/filerepository"], returnFirstDependency); - } else { - define("transfermanager", [apiClientBowerPath + "/sync/transfermanager"], returnFirstDependency); - define("filerepository", [apiClientBowerPath + "/sync/filerepository"], returnFirstDependency); - } - + define("transfermanager", [apiClientBowerPath + "/sync/transfermanager"], returnFirstDependency); + define("filerepository", [apiClientBowerPath + "/sync/filerepository"], returnFirstDependency); define("localsync", [apiClientBowerPath + "/sync/localsync"], returnFirstDependency); } From 071963ec5a79f1552579fdaf474be088c93255a0 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 21:48:44 +0000 Subject: [PATCH 106/220] added nativeshell API to filedownloader module --- src/components/filedownloader.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/components/filedownloader.js b/src/components/filedownloader.js index c8e3011be2..c5810b460e 100644 --- a/src/components/filedownloader.js +++ b/src/components/filedownloader.js @@ -4,9 +4,15 @@ define(['multi-download'], function (multiDownload) { return { download: function (items) { - multiDownload(items.map(function (item) { - return item.url; - })); + if (window.NativeShell) { + items.map(function (item) { + window.NativeShell.downloadFile(item.url); + }); + } else { + multiDownload(items.map(function (item) { + return item.url; + })); + } } }; }); \ No newline at end of file From 01d38d04bacb62edd05d3bf5c2f55a87417c3f2e Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 21:49:05 +0000 Subject: [PATCH 107/220] removed require for module cordova filedownloader --- src/scripts/site.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 222717969c..d97b5d3bf2 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -482,13 +482,7 @@ var AppInfo = {}; } define("multi-download", [componentsPath + "/multidownload"], returnFirstDependency); - - if ("android" === self.appMode) { - define("fileDownloader", ["cordova/filedownloader"], returnFirstDependency); - } else { - define("fileDownloader", [componentsPath + "/filedownloader"], returnFirstDependency); - } - + define("fileDownloader", [componentsPath + "/filedownloader"], returnFirstDependency); define("localassetmanager", [apiClientBowerPath + "/localassetmanager"], returnFirstDependency); if ("cordova" === self.appMode || "android" === self.appMode) { From 7fc4165b538c105a4a0c65644d269c3622238088 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 16 Mar 2019 22:56:55 +0000 Subject: [PATCH 108/220] remove some require modules of cordova --- src/scripts/site.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index d97b5d3bf2..d2a01c873e 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1160,11 +1160,7 @@ var AppInfo = {}; require(["components/thememediaplayer", "scripts/autobackdrops"]); if ("cordova" === self.appMode || "android" === self.appMode) { - if (browser.android) { - require(["cordova/mediasession"]); - } else if (browser.safari) { - require(["cordova/mediasession", "cordova/volume", "cordova/statusbar", "cordova/backgroundfetch"]); - } + require(["cordova/mediasession"]); } if (!browser.tv && !browser.xboxOne && !browser.ps4) { From e4c7282b92ce5f4f96655410adcfc57aa3a765bf Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sun, 17 Mar 2019 00:31:56 +0000 Subject: [PATCH 109/220] refactor mediaSession to support NativeShell API --- src/components/playback/mediasession.js | 170 ++++++++++++++++-------- 1 file changed, 116 insertions(+), 54 deletions(-) diff --git a/src/components/playback/mediasession.js b/src/components/playback/mediasession.js index 8e2f7d0c01..fc899918f6 100644 --- a/src/components/playback/mediasession.js +++ b/src/components/playback/mediasession.js @@ -1,5 +1,10 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], function (playbackManager, nowPlayingHelper, events, connectionManager) { "use strict"; + + // no support for mediaSession + if (!navigator.mediaSession && !window.NativeShell) { + return; + } // Reports media playback to the device for lock screen control @@ -64,15 +69,16 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f return null; } - function pushImageUrl(item, height, list) { - - var imageOptions = { - height: height - }; - + function pushImageUrl(item, imageOptions, list) { var url = seriesImageUrl(item, imageOptions) || imageUrl(item, imageOptions); + if (url) { - list.push({ src: url, sizes: height + 'x' + height }); + var height = imageOptions.height || imageOptions.maxHeight; + + list.push({ + src: url, + sizes: height + 'x' + height + }); } } @@ -80,12 +86,12 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f var list = []; - pushImageUrl(item, 96, list); - pushImageUrl(item, 128, list); - pushImageUrl(item, 192, list); - pushImageUrl(item, 256, list); - pushImageUrl(item, 384, list); - pushImageUrl(item, 512, list); + pushImageUrl(item, {height: 96}, list); + pushImageUrl(item, {height: 128}, list); + pushImageUrl(item, {height: 192}, list); + pushImageUrl(item, {height: 256}, list); + pushImageUrl(item, {height: 384}, list); + pushImageUrl(item, {height: 512}, list); return list; } @@ -99,6 +105,19 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f return; } + // dummy this up + if (eventName == 'init') { + eventName = 'timeupdate'; + } + + var isVideo = item.MediaType === 'Video'; + var isLocalPlayer = player.isLocalPlayer || false; + + // Local players do their own notifications + if (isLocalPlayer && isVideo) { + return; + } + var playState = state.PlayState || {}; var parts = nowPlayingHelper.getNowPlayingNames(item); @@ -106,8 +125,6 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f var artist = parts.length === 1 ? '' : parts[0].text; var title = parts[parts.length - 1].text; - var isVideo = item.MediaType === 'Video'; - // Switch these two around for video if (isVideo && parts.length > 1) { var temp = artist; @@ -131,18 +148,54 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f var isPaused = playState.IsPaused || false; var canSeek = playState.CanSeek || false; - navigator.mediaSession.metadata = new MediaMetadata({ - title: title, - artist: artist, - album: album, - artwork: getImageUrls(item), - albumArtist: albumArtist, - currentTime: currentTime, - duration: duration, - paused: isPaused, - itemId: itemId, - mediaType: item.MediaType - }); + var now = new Date().getTime(); + + // Don't go crazy reporting position changes + if (eventName == 'timeupdate' && (now - lastUpdateTime) < 5000) { + // Only report if this item hasn't been reported yet, or if there's an actual playback change. + // Don't report on simple time updates + return; + } + + lastUpdateTime = now; + + if (navigator.mediaSession){ + navigator.mediaSession.metadata = new MediaMetadata({ + title: title, + artist: artist, + album: album, + artwork: getImageUrls(item), + albumArtist: albumArtist, + currentTime: currentTime, + duration: duration, + paused: isPaused, + itemId: itemId, + mediaType: item.MediaType + }); + } else { + var imageUrl = []; + pushImageUrl(item, {maxHeight: 400}, imageUrl); + + if (imageUrl.length) { + imageUrl = imageUrl[0].src; + } else { + imageUrl = null; + } + + window.NativeShell.updateMediaSession({ + action: eventName, + isLocalPlayer: isLocalPlayer, + itemId: itemId, + title: title, + artist: artist, + album: album, + duration: duration, + position: currentTime, + imageUrl: imageUrl, + canSeek: canSeek, + isPaused: isPaused + }); + } } function onGeneralEvent(e) { @@ -191,7 +244,13 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f } function hideMediaControls() { - navigator.mediaSession.metadata = null; + lastUpdateTime = 0; + + if (navigator.mediaSession) { + navigator.mediaSession.metadata = null; + } else { + window.NativeShell.hideMediaSession(); + } } function bindToPlayer(player) { @@ -215,34 +274,37 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f events.on(currentPlayer, 'timeupdate', onGeneralEvent); } - function execute(name) { - playbackManager[name](currentPlayer); + if (navigator.mediaSession) { + + function execute(name) { + playbackManager[name](currentPlayer); + } + + navigator.mediaSession.setActionHandler('previoustrack', function () { + execute('previousTrack'); + }); + + navigator.mediaSession.setActionHandler('nexttrack', function () { + execute('nextTrack'); + }); + + navigator.mediaSession.setActionHandler('play', function () { + execute('unpause'); + }); + + navigator.mediaSession.setActionHandler('pause', function () { + execute('pause'); + }); + + navigator.mediaSession.setActionHandler('seekbackward', function () { + execute('rewind'); + }); + + navigator.mediaSession.setActionHandler('seekforward', function () { + execute('fastForward'); + }); } - navigator.mediaSession.setActionHandler('previoustrack', function () { - execute('previousTrack'); - }); - - navigator.mediaSession.setActionHandler('nexttrack', function () { - execute('nextTrack'); - }); - - navigator.mediaSession.setActionHandler('play', function () { - execute('unpause'); - }); - - navigator.mediaSession.setActionHandler('pause', function () { - execute('pause'); - }); - - navigator.mediaSession.setActionHandler('seekbackward', function () { - execute('rewind'); - }); - - navigator.mediaSession.setActionHandler('seekforward', function () { - execute('fastForward'); - }); - events.on(playbackManager, 'playerchange', function () { bindToPlayer(playbackManager.getCurrentPlayer()); From 01d82010ed5353bd16ff5c9ab772e37a10f430f5 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sun, 17 Mar 2019 00:32:15 +0000 Subject: [PATCH 110/220] cleanup for mediaSession require --- src/scripts/site.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index d2a01c873e..83c3b8bde2 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1159,10 +1159,6 @@ var AppInfo = {}; require(["components/thememediaplayer", "scripts/autobackdrops"]); - if ("cordova" === self.appMode || "android" === self.appMode) { - require(["cordova/mediasession"]); - } - if (!browser.tv && !browser.xboxOne && !browser.ps4) { require(["components/nowplayingbar/nowplayingbar"]); } @@ -1175,11 +1171,7 @@ var AppInfo = {}; require(["components/playback/volumeosd"]); } - if (navigator.mediaSession) { - require(["mediaSession"]); - } - - require(["serverNotifications"]); + require(["mediaSession", "serverNotifications"]); if (!browser.tv && !browser.xboxOne) { require(["components/playback/playbackorientation"]); From dab41fe6e15c802509023e1ccef591601dd88a59 Mon Sep 17 00:00:00 2001 From: Phallacy Date: Sun, 17 Mar 2019 01:13:12 -0700 Subject: [PATCH 111/220] made the main save and load methods that I modified more legible --- src/scripts/useredit.js | 63 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/src/scripts/useredit.js b/src/scripts/useredit.js index 62c9ed37c6..916a09e402 100644 --- a/src/scripts/useredit.js +++ b/src/scripts/useredit.js @@ -22,13 +22,42 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, l } function loadUser(page, user) { - currentUser = user, ApiClient.getJSON(ApiClient.getUrl("Auth/Providers")).then(function(providers) { + currentUser = user, + ApiClient.getJSON(ApiClient.getUrl("Auth/Providers")).then(function(providers) { loadAuthProviders(page, user, providers) - }), ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", { + }), + ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", { IsHidden: !1 })).then(function(folders) { loadDeleteFolders(page, user, folders.Items) - }), user.Policy.IsDisabled ? $(".disabledUserBanner", page).show() : $(".disabledUserBanner", page).hide(), "Guest" == user.ConnectLinkType ? ($("#fldConnectInfo", page).hide(), $("#txtUserName", page).prop("disabled", "disabled")) : ($("#txtUserName", page).prop("disabled", "").removeAttr("disabled"), $("#fldConnectInfo", page).show()), $(".lnkEditUserPreferences", page).attr("href", "mypreferencesmenu.html?userId=" + user.Id), libraryMenu.setTitle(user.Name), page.querySelector(".username").innerHTML = user.Name, $("#txtUserName", page).val(user.Name), $("#chkIsAdmin", page).checked(user.Policy.IsAdministrator), $("#chkDisabled", page).checked(user.Policy.IsDisabled), $("#chkIsHidden", page).checked(user.Policy.IsHidden), $("#chkRemoteControlSharedDevices", page).checked(user.Policy.EnableSharedDeviceControl), $("#chkEnableRemoteControlOtherUsers", page).checked(user.Policy.EnableRemoteControlOfOtherUsers), $("#chkEnableDownloading", page).checked(user.Policy.EnableContentDownloading), $("#chkManageLiveTv", page).checked(user.Policy.EnableLiveTvManagement), $("#chkEnableLiveTvAccess", page).checked(user.Policy.EnableLiveTvAccess), $("#chkEnableMediaPlayback", page).checked(user.Policy.EnableMediaPlayback), $("#chkEnableAudioPlaybackTranscoding", page).checked(user.Policy.EnableAudioPlaybackTranscoding), $("#chkEnableVideoPlaybackTranscoding", page).checked(user.Policy.EnableVideoPlaybackTranscoding), $("#chkEnableVideoPlaybackRemuxing", page).checked(user.Policy.EnablePlaybackRemuxing), $("#chkRemoteAccess", page).checked(null == user.Policy.EnableRemoteAccess || user.Policy.EnableRemoteAccess), $("#chkEnableSyncTranscoding", page).checked(user.Policy.EnableSyncTranscoding), $("#chkEnableConversion", page).checked(user.Policy.EnableMediaConversion || !1), $("#chkEnableSharing", page).checked(user.Policy.EnablePublicSharing), $("#txtRemoteClientBitrateLimit", page).val(user.Policy.RemoteClientBitrateLimit / 1e6 || ""), $("#txtLoginAttemptsBeforeLockout", page).val(user.Policy.LoginAttemptsBeforeLockout || "0"), loading.hide() + }), + user.Policy.IsDisabled ? $(".disabledUserBanner", page).show() : $(".disabledUserBanner", page).hide(), + "Guest" == user.ConnectLinkType ? ($("#fldConnectInfo", page).hide(), + $("#txtUserName", page).prop("disabled", "disabled")) : ($("#txtUserName", page).prop("disabled", "").removeAttr("disabled"), + $("#fldConnectInfo", page).show()), + $(".lnkEditUserPreferences", page).attr("href", "mypreferencesmenu.html?userId=" + user.Id), + libraryMenu.setTitle(user.Name), + page.querySelector(".username").innerHTML = user.Name, + $("#txtUserName", page).val(user.Name), + $("#chkIsAdmin", page).checked(user.Policy.IsAdministrator), + $("#chkDisabled", page).checked(user.Policy.IsDisabled), + $("#chkIsHidden", page).checked(user.Policy.IsHidden), + $("#chkRemoteControlSharedDevices", page).checked(user.Policy.EnableSharedDeviceControl), + $("#chkEnableRemoteControlOtherUsers", page).checked(user.Policy.EnableRemoteControlOfOtherUsers), + $("#chkEnableDownloading", page).checked(user.Policy.EnableContentDownloading), + $("#chkManageLiveTv", page).checked(user.Policy.EnableLiveTvManagement), + $("#chkEnableLiveTvAccess", page).checked(user.Policy.EnableLiveTvAccess), + $("#chkEnableMediaPlayback", page).checked(user.Policy.EnableMediaPlayback), + $("#chkEnableAudioPlaybackTranscoding", page).checked(user.Policy.EnableAudioPlaybackTranscoding), + $("#chkEnableVideoPlaybackTranscoding", page).checked(user.Policy.EnableVideoPlaybackTranscoding), + $("#chkEnableVideoPlaybackRemuxing", page).checked(user.Policy.EnablePlaybackRemuxing), + $("#chkRemoteAccess", page).checked(null == user.Policy.EnableRemoteAccess || user.Policy.EnableRemoteAccess), + $("#chkEnableSyncTranscoding", page).checked(user.Policy.EnableSyncTranscoding), + $("#chkEnableConversion", page).checked(user.Policy.EnableMediaConversion || !1), + $("#chkEnableSharing", page).checked(user.Policy.EnablePublicSharing), + $("#txtRemoteClientBitrateLimit", page).val(user.Policy.RemoteClientBitrateLimit / 1e6 || ""), + $("#txtLoginAttemptsBeforeLockout", page).val(user.Policy.LoginAttemptsBeforeLockout || "0"), + loading.hide() } function onSaveComplete(page, user) { @@ -40,11 +69,33 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, l } function saveUser(user, page) { - user.Name = $("#txtUserName", page).val(), user.Policy.IsAdministrator = $("#chkIsAdmin", page).checked(), user.Policy.IsHidden = $("#chkIsHidden", page).checked(), user.Policy.IsDisabled = $("#chkDisabled", page).checked(), user.Policy.EnableRemoteControlOfOtherUsers = $("#chkEnableRemoteControlOtherUsers", page).checked(), user.Policy.EnableLiveTvManagement = $("#chkManageLiveTv", page).checked(), user.Policy.EnableLiveTvAccess = $("#chkEnableLiveTvAccess", page).checked(), user.Policy.EnableSharedDeviceControl = $("#chkRemoteControlSharedDevices", page).checked(), user.Policy.EnableMediaPlayback = $("#chkEnableMediaPlayback", page).checked(), user.Policy.EnableAudioPlaybackTranscoding = $("#chkEnableAudioPlaybackTranscoding", page).checked(), user.Policy.EnableVideoPlaybackTranscoding = $("#chkEnableVideoPlaybackTranscoding", page).checked(), user.Policy.EnablePlaybackRemuxing = $("#chkEnableVideoPlaybackRemuxing", page).checked(), user.Policy.EnableContentDownloading = $("#chkEnableDownloading", page).checked(), user.Policy.EnableSyncTranscoding = $("#chkEnableSyncTranscoding", page).checked(), user.Policy.EnableMediaConversion = $("#chkEnableConversion", page).checked(), user.Policy.EnablePublicSharing = $("#chkEnableSharing", page).checked(), user.Policy.EnableRemoteAccess = $("#chkRemoteAccess", page).checked(), user.Policy.RemoteClientBitrateLimit = parseInt(1e6 * parseFloat($("#txtRemoteClientBitrateLimit", page).val() || "0")), user.Policy.LoginAttemptsBeforeLockout = parseInt($("#txtLoginAttemptsBeforeLockout", page).val() || "0"), user.Policy.AuthenticationProviderId = page.querySelector(".selectLoginProvider").value, user.Policy.EnableContentDeletion = $("#chkEnableDeleteAllFolders", page).checked(), user.Policy.EnableContentDeletionFromFolders = user.Policy.EnableContentDeletion ? [] : $(".chkFolder", page).get().filter(function(c) { - return c.checked + user.Name = $("#txtUserName", page).val(), + user.Policy.IsAdministrator = $("#chkIsAdmin", page).checked(), + user.Policy.IsHidden = $("#chkIsHidden", page).checked(), + user.Policy.IsDisabled = $("#chkDisabled", page).checked(), + user.Policy.EnableRemoteControlOfOtherUsers = $("#chkEnableRemoteControlOtherUsers", page).checked(), + user.Policy.EnableLiveTvManagement = $("#chkManageLiveTv", page).checked(), + user.Policy.EnableLiveTvAccess = $("#chkEnableLiveTvAccess", page).checked(), + user.Policy.EnableSharedDeviceControl = $("#chkRemoteControlSharedDevices", page).checked(), + user.Policy.EnableMediaPlayback = $("#chkEnableMediaPlayback", page).checked(), + user.Policy.EnableAudioPlaybackTranscoding = $("#chkEnableAudioPlaybackTranscoding", page).checked(), + user.Policy.EnableVideoPlaybackTranscoding = $("#chkEnableVideoPlaybackTranscoding", page).checked(), + user.Policy.EnablePlaybackRemuxing = $("#chkEnableVideoPlaybackRemuxing", page).checked(), + user.Policy.EnableContentDownloading = $("#chkEnableDownloading", page).checked(), + user.Policy.EnableSyncTranscoding = $("#chkEnableSyncTranscoding", page).checked(), + user.Policy.EnableMediaConversion = $("#chkEnableConversion", page).checked(), + user.Policy.EnablePublicSharing = $("#chkEnableSharing", page).checked(), + user.Policy.EnableRemoteAccess = $("#chkRemoteAccess", page).checked(), + user.Policy.RemoteClientBitrateLimit = parseInt(1e6 * parseFloat($("#txtRemoteClientBitrateLimit", page).val() || "0")), + user.Policy.LoginAttemptsBeforeLockout = parseInt($("#txtLoginAttemptsBeforeLockout", page).val() || "0"), + user.Policy.AuthenticationProviderId = page.querySelector(".selectLoginProvider").value, + user.Policy.EnableContentDeletion = $("#chkEnableDeleteAllFolders", page).checked(), + user.Policy.EnableContentDeletionFromFolders = user.Policy.EnableContentDeletion ? [] : $(".chkFolder", page).get().filter(function(c) { + return c.checked }).map(function(c) { return c.getAttribute("data-id") - }), ApiClient.updateUser(user).then(function() { + }), + ApiClient.updateUser(user).then(function() { ApiClient.updateUserPolicy(user.Id, user.Policy).then(function() { onSaveComplete(page, user) }) From e29b0be9fd7a622fe24b0517a5e337aa32372630 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Sun, 17 Mar 2019 22:13:56 +0100 Subject: [PATCH 112/220] Remove no to nb --- src/strings/{no.json => nb.json} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/strings/{no.json => nb.json} (100%) diff --git a/src/strings/no.json b/src/strings/nb.json similarity index 100% rename from src/strings/no.json rename to src/strings/nb.json From 447ec2c3abd15aeac05e1acdc4b4e70c8fa39520 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Sun, 17 Mar 2019 22:24:49 +0100 Subject: [PATCH 113/220] Return inner promise in init require --- src/scripts/site.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index e1d91ee99c..c9b1e7fee8 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -275,7 +275,7 @@ var AppInfo = {}; var credentialProviderInstance = new credentialProvider(); var promises = [apphost.getSyncProfile(), apphost.init()]; - Promise.all(promises).then(function (responses) { + return Promise.all(promises).then(function (responses) { var deviceProfile = responses[0]; var capabilities = Dashboard.capabilities(apphost); @@ -293,7 +293,7 @@ var AppInfo = {}; console.log("creating ApiClient singleton"); var apiClient = new apiClientFactory(Dashboard.serverAddress(), apphost.appName(), apphost.appVersion(), apphost.deviceName(), apphost.deviceId(), window.devicePixelRatio); - + apiClient.enableAutomaticNetworking = false; apiClient.manualAddressOnly = true; From 91ef01cbc00328438afb3b8d17d0e271ae191aa6 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sun, 17 Mar 2019 21:42:36 +0000 Subject: [PATCH 114/220] removed require for cordova externalPlayer --- src/scripts/site.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 83c3b8bde2..5d1f70df67 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1095,10 +1095,6 @@ var AppInfo = {}; "components/youtubeplayer/plugin" ]; - if ("android" === self.appMode) { - list.push("cordova/externalplayer"); - } - if (appHost.supports("remotecontrol")) { list.push("components/sessionplayer"); From 9967edcb353813393d9093a273af0aac8c190421 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sun, 17 Mar 2019 21:52:56 +0000 Subject: [PATCH 115/220] deuglify apphost.js --- src/components/apphost.js | 444 ++++++++++++++++++++++++++++---------- 1 file changed, 329 insertions(+), 115 deletions(-) diff --git a/src/components/apphost.js b/src/components/apphost.js index 9cffd2d8a4..21d474a3e1 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -1,109 +1,178 @@ -define(["appSettings", "browser", "events", "htmlMediaHelper"], function(appSettings, browser, events, htmlMediaHelper) { +define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSettings, browser, events, htmlMediaHelper) { "use strict"; function getBaseProfileOptions(item) { var disableHlsVideoAudioCodecs = []; - return item && htmlMediaHelper.enableHlsJsPlayer(item.RunTimeTicks, item.MediaType) && ((browser.edge || browser.msie) && disableHlsVideoAudioCodecs.push("mp3"), disableHlsVideoAudioCodecs.push("ac3"), disableHlsVideoAudioCodecs.push("eac3"), disableHlsVideoAudioCodecs.push("opus")), { - enableMkvProgressive: !1, - disableHlsVideoAudioCodecs: disableHlsVideoAudioCodecs + + if (item && htmlMediaHelper.enableHlsJsPlayer(item.RunTimeTicks, item.MediaType)) { + if (browser.edge || browser.msie) { + disableHlsVideoAudioCodecs.push("mp3"); + } + + disableHlsVideoAudioCodecs.push("ac3"); + disableHlsVideoAudioCodecs.push("eac3"); + disableHlsVideoAudioCodecs.push("opus"); } + + return { + enableMkvProgressive: false, + disableHlsVideoAudioCodecs: disableHlsVideoAudioCodecs + }; } function getDeviceProfileForWindowsUwp(item) { - return new Promise(function(resolve, reject) { - require(["browserdeviceprofile", "environments/windows-uwp/mediacaps"], function(profileBuilder, uwpMediaCaps) { + return new Promise(function (resolve, reject) { + require(["browserdeviceprofile", "environments/windows-uwp/mediacaps"], function (profileBuilder, uwpMediaCaps) { var profileOptions = getBaseProfileOptions(item); - profileOptions.supportsDts = uwpMediaCaps.supportsDTS(), profileOptions.supportsTrueHd = uwpMediaCaps.supportsDolby(), profileOptions.audioChannels = uwpMediaCaps.getAudioChannels(), resolve(profileBuilder(profileOptions)) - }) - }) + profileOptions.supportsDts = uwpMediaCaps.supportsDTS(); + profileOptions.supportsTrueHd = uwpMediaCaps.supportsDolby(); + profileOptions.audioChannels = uwpMediaCaps.getAudioChannels(); + resolve(profileBuilder(profileOptions)); + }); + }); } function getDeviceProfile(item, options) { - return options = options || {}, self.Windows ? getDeviceProfileForWindowsUwp(item) : new Promise(function(resolve, reject) { - require(["browserdeviceprofile"], function(profileBuilder) { + options = options || {}; + + if (self.Windows) { + return getDeviceProfileForWindowsUwp(item); + } + + return new Promise(function (resolve, reject) { + require(["browserdeviceprofile"], function (profileBuilder) { var profile = profileBuilder(getBaseProfileOptions(item)); - item && !options.isRetry && "allcomplexformats" !== appSettings.get("subtitleburnin") && (browser.orsay || browser.tizen || (profile.SubtitleProfiles.push({ - Format: "ass", - Method: "External" - }), profile.SubtitleProfiles.push({ - Format: "ssa", - Method: "External" - }))), resolve(profile) - }) - }) + + if (item && !options.isRetry && "allcomplexformats" !== appSettings.get("subtitleburnin")) { + if (!(browser.orsay || browser.tizen)) { + profile.SubtitleProfiles.push({ + Format: "ass", + Method: "External" + }); + profile.SubtitleProfiles.push({ + Format: "ssa", + Method: "External" + }); + } + } + + resolve(profile); + }); + }); } function escapeRegExp(str) { - return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1") + return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); } function replaceAll(originalString, strReplace, strWith) { - var strReplace2 = escapeRegExp(strReplace), - reg = new RegExp(strReplace2, "ig"); - return originalString.replace(reg, strWith) + var strReplace2 = escapeRegExp(strReplace); + var reg = new RegExp(strReplace2, "ig"); + return originalString.replace(reg, strWith); } function generateDeviceId() { var keys = []; - if (keys.push(navigator.userAgent), keys.push((new Date).getTime()), self.btoa) { + + if (keys.push(navigator.userAgent), keys.push(new Date().getTime()), self.btoa) { var result = replaceAll(btoa(keys.join("|")), "=", "1"); - return Promise.resolve(result) + return Promise.resolve(result); } - return Promise.resolve((new Date).getTime()) + + return Promise.resolve(new Date().getTime()); } function getDeviceId() { - var key = "_deviceId2", - deviceId = appSettings.get(key); - return deviceId ? Promise.resolve(deviceId) : generateDeviceId().then(function(deviceId) { - return appSettings.set(key, deviceId), deviceId - }) + var key = "_deviceId2"; + var deviceId = appSettings.get(key); + + if (deviceId) { + return Promise.resolve(deviceId); + } + + return generateDeviceId().then(function (deviceId) { + appSettings.set(key, deviceId); + return deviceId; + }); } function getDeviceName() { var deviceName; - return deviceName = browser.tizen ? "Samsung Smart TV" : browser.web0s ? "LG Smart TV" : browser.operaTv ? "Opera TV" : browser.xboxOne ? "Xbox One" : browser.ps4 ? "Sony PS4" : browser.chrome ? "Chrome" : browser.edge ? "Edge" : browser.firefox ? "Firefox" : browser.msie ? "Internet Explorer" : browser.opera ? "Opera" : "Web Browser", browser.ipad ? deviceName += " Ipad" : browser.iphone ? deviceName += " Iphone" : browser.android && (deviceName += " Android"), deviceName + deviceName = browser.tizen ? "Samsung Smart TV" : browser.web0s ? "LG Smart TV" : browser.operaTv ? "Opera TV" : browser.xboxOne ? "Xbox One" : browser.ps4 ? "Sony PS4" : browser.chrome ? "Chrome" : browser.edge ? "Edge" : browser.firefox ? "Firefox" : browser.msie ? "Internet Explorer" : browser.opera ? "Opera" : "Web Browser"; + + if (browser.ipad) { + deviceName += " Ipad"; + } else { + if (browser.iphone) { + deviceName += " Iphone"; + } else { + if (browser.android) { + deviceName += " Android"; + } + } + } + + return deviceName; } function supportsVoiceInput() { - return !browser.tv && (window.SpeechRecognition || window.webkitSpeechRecognition || window.mozSpeechRecognition || window.oSpeechRecognition || window.msSpeechRecognition) + if (!browser.tv) { + return window.SpeechRecognition || window.webkitSpeechRecognition || window.mozSpeechRecognition || window.oSpeechRecognition || window.msSpeechRecognition; + } + + return false; } function supportsFullscreen() { - if (browser.tv) return !1; + if (browser.tv) { + return false; + } + var element = document.documentElement; - return !!(element.requestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen || element.msRequestFullscreen) || !!document.createElement("video").webkitEnterFullscreen + return !!(element.requestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen || element.msRequestFullscreen) || !!document.createElement("video").webkitEnterFullscreen; } function getSyncProfile() { - return new Promise(function(resolve, reject) { - require(["browserdeviceprofile", "appSettings"], function(profileBuilder, appSettings) { + return new Promise(function (resolve, reject) { + require(["browserdeviceprofile", "appSettings"], function (profileBuilder, appSettings) { var profile = profileBuilder(); - profile.MaxStaticMusicBitrate = appSettings.maxStaticMusicBitrate(), resolve(profile) - }) - }) + profile.MaxStaticMusicBitrate = appSettings.maxStaticMusicBitrate(); + resolve(profile); + }); + }); } function getDefaultLayout() { - return "desktop" + return "desktop"; } function supportsHtmlMediaAutoplay() { - if (browser.edgeUwp || browser.tizen || browser.web0s || browser.orsay || browser.operaTv || browser.ps4 || browser.xboxOne) return !0; - if (browser.mobile) return !1; + if (browser.edgeUwp || browser.tizen || browser.web0s || browser.orsay || browser.operaTv || browser.ps4 || browser.xboxOne) { + return true; + } + + if (browser.mobile) { + return false; + } + var savedResult = appSettings.get(htmlMediaAutoplayAppStorageKey); - return "true" === savedResult || "false" !== savedResult && null + return "true" === savedResult || "false" !== savedResult && null; } function cueSupported() { try { - var video = document.createElement("video"), - style = document.createElement("style"); - style.textContent = "video::cue {background: inherit}", document.body.appendChild(style), document.body.appendChild(video); + var video = document.createElement("video"); + var style = document.createElement("style"); + style.textContent = "video::cue {background: inherit}"; + document.body.appendChild(style); + document.body.appendChild(video); var cue = window.getComputedStyle(video, "::cue").background; - return document.body.removeChild(style), document.body.removeChild(video), !!cue.length + document.body.removeChild(style); + document.body.removeChild(video); + return !!cue.length; } catch (err) { - return console.log("Error detecting cue support:" + err), !1 + console.log("Error detecting cue support:" + err); + return false; } } @@ -123,41 +192,104 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function(appSett } var htmlMediaAutoplayAppStorageKey = "supportshtmlmediaautoplay0"; - var supportedFeatures = function() { + + var supportedFeatures = function () { var features = []; - navigator.share && features.push("sharing"); - browser.edgeUwp || browser.tv || browser.xboxOne || browser.ps4 || features.push("filedownload"); - browser.operaTv || browser.tizen || browser.orsay || browser.web0s - ? features.push("exit") - : (features.push("exitmenu"), features.push("plugins")); - browser.operaTv || browser.tizen || browser.orsay || browser.web0s || browser.ps4 || (features.push("externallinks"), features.push("externalpremium")); - browser.operaTv || features.push("externallinkdisplay"); - supportsVoiceInput() && features.push("voiceinput"); - !browser.tv && !browser.xboxOne && browser.ps4, supportsHtmlMediaAutoplay() && (features.push("htmlaudioautoplay"), features.push("htmlvideoautoplay")); - browser.edgeUwp && features.push("sync"); - supportsFullscreen() && features.push("fullscreenchange"); - (browser.chrome || browser.edge && !browser.slow) && (browser.noAnimation || browser.edgeUwp || browser.xboxOne || features.push("imageanalysis")); - (browser.tv || browser.xboxOne || browser.ps4 || browser.mobile) && features.push("physicalvolumecontrol"); - browser.tv || browser.xboxOne || browser.ps4 || features.push("remotecontrol"); - browser.operaTv || browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp || features.push("remotevideo"); + + if (navigator.share) { + features.push("sharing"); + } + + if (!(browser.edgeUwp || browser.tv || browser.xboxOne || browser.ps4)) { + features.push("filedownload"); + } + + if (browser.operaTv || browser.tizen || browser.orsay || browser.web0s) { + features.push("exit"); + } else { + features.push("exitmenu"); + features.push("plugins"); + } + + if (!(browser.operaTv || browser.tizen || browser.orsay || browser.web0s || browser.ps4)) { + features.push("externallinks"); + features.push("externalpremium"); + } + + if (!browser.operaTv) { + features.push("externallinkdisplay"); + } + + if (supportsVoiceInput()) { + features.push("voiceinput"); + } + + if (!browser.tv && !browser.xboxOne) { + browser.ps4; + } + + if (supportsHtmlMediaAutoplay()) { + features.push("htmlaudioautoplay"); + features.push("htmlvideoautoplay"); + } + + if (browser.edgeUwp) { + features.push("sync"); + } + + if (supportsFullscreen()) { + features.push("fullscreenchange"); + } + + if (browser.chrome || browser.edge && !browser.slow) { + if (!(browser.noAnimation || browser.edgeUwp || browser.xboxOne)) { + features.push("imageanalysis"); + } + } + + if (browser.tv || browser.xboxOne || browser.ps4 || browser.mobile) { + features.push("physicalvolumecontrol"); + } + + if (!(browser.tv || browser.xboxOne || browser.ps4)) { + features.push("remotecontrol"); + } + + if (!(browser.operaTv || browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp)) { + features.push("remotevideo"); + } + features.push("displaylanguage"); features.push("otherapppromotions"); - features.push("targetblank"); - // allows users to connect to more than one server + features.push("targetblank"); // allows users to connect to more than one server //features.push("multiserver"); - browser.orsay || browser.tizen || browser.msie || !(browser.firefox || browser.ps4 || browser.edge || cueSupported()) || features.push("subtitleappearancesettings"); - browser.orsay || browser.tizen || features.push("subtitleburnsettings"); - browser.tv || browser.ps4 || browser.xboxOne || features.push("fileinput"); - browser.chrome && features.push("chromecast"); + + if (!(browser.orsay || browser.tizen || browser.msie || !(browser.firefox || browser.ps4 || browser.edge || cueSupported()))) { + features.push("subtitleappearancesettings"); + } + + if (!(browser.orsay || browser.tizen)) { + features.push("subtitleburnsettings"); + } + + if (!(browser.tv || browser.ps4 || browser.xboxOne)) { + features.push("fileinput"); + } + + if (browser.chrome) { + features.push("chromecast"); + } + return features; }(); + if (supportedFeatures.indexOf("htmlvideoautoplay") === -1 && supportsHtmlMediaAutoplay() !== false) { - require(["autoPlayDetect"], function(autoPlayDetect) { - autoPlayDetect.supportsHtmlMediaAutoplay().then(function() { + require(["autoPlayDetect"], function (autoPlayDetect) { + autoPlayDetect.supportsHtmlMediaAutoplay().then(function () { appSettings.set(htmlMediaAutoplayAppStorageKey, "true"); supportedFeatures.push("htmlvideoautoplay"); supportedFeatures.push("htmlaudioautoplay"); - }, function() { + }, function () { appSettings.set(htmlMediaAutoplayAppStorageKey, "false"); }); }); @@ -169,73 +301,155 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function(appSett var visibilityState; var appVersion = window.dashboardVersion || "3.0"; var appHost = { - getWindowState: function() { - return document.windowState || "Normal" + getWindowState: function () { + return document.windowState || "Normal"; }, - setWindowState: function(state) { - alert("setWindowState is not supported and should not be called") + setWindowState: function (state) { + alert("setWindowState is not supported and should not be called"); }, - exit: function() { - if (browser.tizen) try { - tizen.application.getCurrentApplication().exit() - } catch (err) { - console.log("error closing application: " + err) - } else window.close() + exit: function () { + if (browser.tizen) { + try { + tizen.application.getCurrentApplication().exit(); + } catch (err) { + console.log("error closing application: " + err); + } + } else { + window.close(); + } }, - supports: function(command) { - return -1 !== supportedFeatures.indexOf(command.toLowerCase()) + supports: function (command) { + return -1 !== supportedFeatures.indexOf(command.toLowerCase()); }, preferVisualCards: browser.android || browser.chrome, moreIcon: browser.android ? "dots-vert" : "dots-horiz", getSyncProfile: getSyncProfile, getDefaultLayout: getDefaultLayout, getDeviceProfile: getDeviceProfile, - init: function() { - return deviceName = getDeviceName(), getDeviceId().then(function(resolvedDeviceId) { - deviceId = resolvedDeviceId - }) + init: function () { + deviceName = getDeviceName(); + return getDeviceId().then(function (resolvedDeviceId) { + deviceId = resolvedDeviceId; + }); }, - deviceName: function() { - return deviceName + deviceName: function () { + return deviceName; }, - deviceId: function() { - return deviceId + deviceId: function () { + return deviceId; }, - appName: function() { - return "Jellyfin Web" + appName: function () { + return "Jellyfin Web"; }, - appVersion: function() { - return appVersion + appVersion: function () { + return appVersion; }, - getPushTokenInfo: function() { - return {} + getPushTokenInfo: function () { + return {}; }, - setThemeColor: function(color) { + setThemeColor: function (color) { var metaThemeColor = document.querySelector("meta[name=theme-color]"); - metaThemeColor && metaThemeColor.setAttribute("content", color) - }, - setUserScalable: function(scalable) { - if (!browser.tv) { - var att = scalable ? "width=device-width, initial-scale=1, minimum-scale=1, user-scalable=yes" : "width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"; - document.querySelector("meta[name=viewport]").setAttribute("content", att) + + if (metaThemeColor) { + metaThemeColor.setAttribute("content", color); } }, - deviceIconUrl: function() { - return browser.edgeUwp, browser.edgeUwp ? "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/windowsrt.png" : browser.opera || browser.operaTv ? "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/opera.png" : browser.orsay || browser.tizen ? "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/samsungtv.png" : browser.web0s ? "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/lgtv.png" : browser.ps4 ? "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/ps4.png" : browser.chromecast ? "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/chromecast.png" : browser.chrome ? "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/chrome.png" : browser.edge ? "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/edge.png" : browser.firefox ? "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/firefox.png" : browser.msie ? "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/internetexplorer.png" : browser.safari ? "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/safari.png" : "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/html5.png" + setUserScalable: function (scalable) { + if (!browser.tv) { + var att = scalable ? "width=device-width, initial-scale=1, minimum-scale=1, user-scalable=yes" : "width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"; + document.querySelector("meta[name=viewport]").setAttribute("content", att); + } + }, + deviceIconUrl: function () { + browser.edgeUwp; + + if (browser.edgeUwp) { + return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/windowsrt.png"; + } + + if (browser.opera || browser.operaTv) { + return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/opera.png"; + } + + if (browser.orsay || browser.tizen) { + return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/samsungtv.png"; + } + + if (browser.web0s) { + return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/lgtv.png"; + } + + if (browser.ps4) { + return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/ps4.png"; + } + + if (browser.chromecast) { + return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/chromecast.png"; + } + + if (browser.chrome) { + return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/chrome.png"; + } + + if (browser.edge) { + return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/edge.png"; + } + + if (browser.firefox) { + return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/firefox.png"; + } + + if (browser.msie) { + return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/internetexplorer.png"; + } + + if (browser.safari) { + return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/safari.png"; + } + + return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/html5.png"; } }; - var doc = self.document; - doc && (void 0 !== doc.visibilityState ? (visibilityChange = "visibilitychange", visibilityState = "hidden") : void 0 !== doc.mozHidden ? (visibilityChange = "mozvisibilitychange", visibilityState = "mozVisibilityState") : void 0 !== doc.msHidden ? (visibilityChange = "msvisibilitychange", visibilityState = "msVisibilityState") : void 0 !== doc.webkitHidden && (visibilityChange = "webkitvisibilitychange", visibilityState = "webkitVisibilityState")); - var isHidden = false; + if (doc) { - doc.addEventListener(visibilityChange, function() { - document[visibilityState] ? onAppHidden() : onAppVisible() + if (void 0 !== doc.visibilityState) { + visibilityChange = "visibilitychange"; + visibilityState = "hidden"; + } else { + if (void 0 !== doc.mozHidden) { + visibilityChange = "mozvisibilitychange"; + visibilityState = "mozVisibilityState"; + } else { + if (void 0 !== doc.msHidden) { + visibilityChange = "msvisibilitychange"; + visibilityState = "msVisibilityState"; + } else { + if (void 0 !== doc.webkitHidden) { + visibilityChange = "webkitvisibilitychange"; + visibilityState = "webkitVisibilityState"; + } + } + } + } + } + + var isHidden = false; + + if (doc) { + doc.addEventListener(visibilityChange, function () { + if (document[visibilityState]) { + onAppHidden(); + } else { + onAppVisible(); + } }); } + if (self.addEventListener) { self.addEventListener("focus", onAppVisible); self.addEventListener("blur", onAppHidden); } + return appHost; }); From 8315f4a2d40398c01e9428e3247e780d5c079577 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sun, 17 Mar 2019 22:02:24 +0000 Subject: [PATCH 116/220] invert some conditions for readability in apphost --- src/components/apphost.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/components/apphost.js b/src/components/apphost.js index 21d474a3e1..d1d865a63a 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -44,7 +44,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet var profile = profileBuilder(getBaseProfileOptions(item)); if (item && !options.isRetry && "allcomplexformats" !== appSettings.get("subtitleburnin")) { - if (!(browser.orsay || browser.tizen)) { + if (!browser.orsay && !browser.tizen) { profile.SubtitleProfiles.push({ Format: "ass", Method: "External" @@ -129,7 +129,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet } var element = document.documentElement; - return !!(element.requestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen || element.msRequestFullscreen) || !!document.createElement("video").webkitEnterFullscreen; + return (element.requestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen || element.msRequestFullscreen) || document.createElement("video").webkitEnterFullscreen; } function getSyncProfile() { @@ -200,7 +200,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet features.push("sharing"); } - if (!(browser.edgeUwp || browser.tv || browser.xboxOne || browser.ps4)) { + if (!browser.edgeUwp && !browser.tv && !browser.xboxOne && !browser.ps4) { features.push("filedownload"); } @@ -211,7 +211,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet features.push("plugins"); } - if (!(browser.operaTv || browser.tizen || browser.orsay || browser.web0s || browser.ps4)) { + if (!browser.operaTv && !browser.tizen && !browser.orsay && !browser.web0s && !browser.ps4) { features.push("externallinks"); features.push("externalpremium"); } @@ -242,7 +242,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet } if (browser.chrome || browser.edge && !browser.slow) { - if (!(browser.noAnimation || browser.edgeUwp || browser.xboxOne)) { + if (!browser.noAnimation && !browser.edgeUwp && !browser.xboxOne) { features.push("imageanalysis"); } } @@ -251,11 +251,11 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet features.push("physicalvolumecontrol"); } - if (!(browser.tv || browser.xboxOne || browser.ps4)) { + if (!browser.tv && !browser.xboxOne && !browser.ps4) { features.push("remotecontrol"); } - if (!(browser.operaTv || browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp)) { + if (!browser.operaTv && !browser.tizen && !browser.orsay && !browser.web0s && !browser.edgeUwp) { features.push("remotevideo"); } @@ -264,15 +264,15 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet features.push("targetblank"); // allows users to connect to more than one server //features.push("multiserver"); - if (!(browser.orsay || browser.tizen || browser.msie || !(browser.firefox || browser.ps4 || browser.edge || cueSupported()))) { + if (!browser.orsay && !browser.tizen && !browser.msie && (browser.firefox || browser.ps4 || browser.edge || cueSupported())) { features.push("subtitleappearancesettings"); } - if (!(browser.orsay || browser.tizen)) { + if (!browser.orsay && !browser.tizen) { features.push("subtitleburnsettings"); } - if (!(browser.tv || browser.ps4 || browser.xboxOne)) { + if (!browser.tv && !browser.ps4 && !browser.xboxOne) { features.push("fileinput"); } From c4ada25fe72f6b169c8eff3fd881bd7f8ee870d9 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sun, 17 Mar 2019 23:23:45 +0000 Subject: [PATCH 117/220] nativeshell API added to apphost --- src/components/apphost.js | 71 +++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/src/components/apphost.js b/src/components/apphost.js index d1d865a63a..369dff0f6f 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -39,20 +39,26 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet return getDeviceProfileForWindowsUwp(item); } - return new Promise(function (resolve, reject) { + return new Promise(function (resolve) { require(["browserdeviceprofile"], function (profileBuilder) { - var profile = profileBuilder(getBaseProfileOptions(item)); + var profile; - if (item && !options.isRetry && "allcomplexformats" !== appSettings.get("subtitleburnin")) { - if (!browser.orsay && !browser.tizen) { - profile.SubtitleProfiles.push({ - Format: "ass", - Method: "External" - }); - profile.SubtitleProfiles.push({ - Format: "ssa", - Method: "External" - }); + if (window.NativeShell) { + profile = window.NativeShell.AppHost.getDeviceProfile(profileBuilder); + } else { + profile = profileBuilder(getBaseProfileOptions(item)); + + if (item && !options.isRetry && "allcomplexformats" !== appSettings.get("subtitleburnin")) { + if (!browser.orsay && !browser.tizen) { + profile.SubtitleProfiles.push({ + Format: "ass", + Method: "External" + }); + profile.SubtitleProfiles.push({ + Format: "ssa", + Method: "External" + }); + } } } @@ -133,10 +139,17 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet } function getSyncProfile() { - return new Promise(function (resolve, reject) { + return new Promise(function (resolve) { require(["browserdeviceprofile", "appSettings"], function (profileBuilder, appSettings) { - var profile = profileBuilder(); - profile.MaxStaticMusicBitrate = appSettings.maxStaticMusicBitrate(); + var profile; + + if (window.NativeShell) { + profile = window.NativeShell.AppHost.getSyncProfile(profileBuilder, appSettings); + } else { + profile = profileBuilder(); + profile.MaxStaticMusicBitrate = appSettings.maxStaticMusicBitrate(); + } + resolve(profile); }); }); @@ -308,7 +321,9 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet alert("setWindowState is not supported and should not be called"); }, exit: function () { - if (browser.tizen) { + if (window.NativeShell) { + window.NativeShell.AppHost.exit(); + } else if (browser.tizen) { try { tizen.application.getCurrentApplication().exit(); } catch (err) { @@ -319,30 +334,44 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet } }, supports: function (command) { + if (window.NativeShell) { + return window.NativeShell.AppHost.supports(command); + } + return -1 !== supportedFeatures.indexOf(command.toLowerCase()); }, preferVisualCards: browser.android || browser.chrome, moreIcon: browser.android ? "dots-vert" : "dots-horiz", getSyncProfile: getSyncProfile, - getDefaultLayout: getDefaultLayout, + getDefaultLayout: function () { + if (window.NativeShell) { + return window.NativeShell.AppHost.getDefaultLayout(); + } + + return getDefaultLayout() + }, getDeviceProfile: getDeviceProfile, init: function () { + if (window.NativeShell) { + return window.NativeShell.AppHost.init(); + } + deviceName = getDeviceName(); return getDeviceId().then(function (resolvedDeviceId) { deviceId = resolvedDeviceId; }); }, deviceName: function () { - return deviceName; + return window.NativeShell ? window.NativeShell.AppHost.deviceName() : deviceName; }, deviceId: function () { - return deviceId; + return window.NativeShell ? window.NativeShell.AppHost.deviceId() : deviceId; }, appName: function () { - return "Jellyfin Web"; + return window.NativeShell ? window.NativeShell.AppHost.appName() : "Jellyfin Web"; }, appVersion: function () { - return appVersion; + return window.NativeShell ? window.NativeShell.AppHost.appVersion() : appVersion; }, getPushTokenInfo: function () { return {}; From 19cb905d5ace5cadcd6adaed86db5ab48cc87461 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sun, 17 Mar 2019 23:23:59 +0000 Subject: [PATCH 118/220] removed require for cordova apphost --- src/scripts/site.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 5d1f70df67..7f8e8aa720 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1373,13 +1373,9 @@ var AppInfo = {}; return viewManager; }); - if ("cordova" === self.appMode || "android" === self.appMode) { - paths.apphost = "cordova/apphost"; - } else { - paths.apphost = "components/apphost"; - } - + paths.apphost = "components/apphost"; paths.appStorage = getAppStorage(apiClientBowerPath); + requirejs.config({ waitSeconds: 0, map: { From e8e098f9b15eb20e0b14e24fb2349e1ffe5e5374 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Mon, 18 Mar 2019 23:08:11 +0000 Subject: [PATCH 119/220] removed nativelshell sync invokation --- src/bower_components/emby-apiclient/sync/localsync.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/bower_components/emby-apiclient/sync/localsync.js b/src/bower_components/emby-apiclient/sync/localsync.js index f2f5f4e9e3..cea244de08 100644 --- a/src/bower_components/emby-apiclient/sync/localsync.js +++ b/src/bower_components/emby-apiclient/sync/localsync.js @@ -3,10 +3,6 @@ define(["connectionManager"], function(connectionManager) { var isSyncing; return { sync: function(options) { - if (window.NativeShell) { - return window.NativeShell.sync(options); - } - return console.log("localSync.sync starting..."), isSyncing ? Promise.resolve() : (isSyncing = !0, new Promise(function(resolve, reject) { require(["multiserversync", "appSettings"], function(MultiServerSync, appSettings) { options = options || {}, options.cameraUploadServers = appSettings.cameraUploadServers(), (new MultiServerSync).sync(connectionManager, options).then(function() { From ae7b8d59f2991de39e05db64737fe90c197b8a61 Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 18 Mar 2019 22:58:48 -0700 Subject: [PATCH 120/220] remove web path modify option --- src/dashboard/dashboardgeneral.js | 18 +----------------- src/dashboardgeneral.html | 10 ---------- src/strings/en-us.json | 2 -- 3 files changed, 1 insertion(+), 29 deletions(-) diff --git a/src/dashboard/dashboardgeneral.js b/src/dashboard/dashboardgeneral.js index 7ecd7cb1c9..ed3b000b12 100644 --- a/src/dashboard/dashboardgeneral.js +++ b/src/dashboard/dashboardgeneral.js @@ -97,7 +97,7 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb $("#txtMetadataPath", view).val(path); } if (networkPath) { - $("#txtMetadataNetworkPath", view).val(networkPath)); + $("#txtMetadataNetworkPath", view).val(networkPath); } picker.close(); }, @@ -109,22 +109,6 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb }) }); - $("#btnSelectWebPath", view).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; - picker.show({ - callback: function(path) { - if (path) { - view.querySelector("#txtWebPath").value = path; - } - picker.close(); - }, - header: Globalize.translate("LabelWebPath"), - instruction: Globalize.translate("LabelWebPathHelp") - }) - }) - }); - $(".dashboardGeneralForm", view).off("submit", onSubmit).on("submit", onSubmit); view.addEventListener("viewshow", function() { var promiseConfig = ApiClient.getServerConfiguration(); diff --git a/src/dashboardgeneral.html b/src/dashboardgeneral.html index 8cc1177167..f95246708f 100644 --- a/src/dashboardgeneral.html +++ b/src/dashboardgeneral.html @@ -55,16 +55,6 @@
${LabelMetadataPathHelp}
- -
-
-
- -
- -
-
${LabelWebPathHelp}
-
diff --git a/src/strings/en-us.json b/src/strings/en-us.json index dca0c0797e..f29c5ac6ff 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -1122,8 +1122,6 @@ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata.", - "LabelWebPath": "Web path:", - "LabelWebPathHelp": "The path where the web client source is located. Do not change this unless you plan on moving the web files, or the web interface will break.", "LabelMetadataReaders": "Metadata readers:", "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.", "LabelMetadataSavers": "Metadata savers:", From 886dec11742a3fc692d3818e28919cf15cb94100 Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 18 Mar 2019 22:22:48 -0700 Subject: [PATCH 121/220] remove all sync and convert buttons --- src/components/categorysyncbuttons.js | 31 - src/components/itemcontextmenu.js | 96 +-- src/components/multiselect/multiselect.js | 40 - src/components/serviceworker/notifications.js | 8 - src/components/serviceworker/sync.js | 6 - src/components/sync/emby-downloadbutton.js | 188 ----- src/components/sync/sync.js | 736 ------------------ src/itemdetails.html | 12 - src/livetv.html | 4 - src/movies.html | 3 - src/scripts/itemdetailpage.js | 64 +- src/scripts/livetvrecordings.js | 3 +- src/scripts/moviesrecommended.js | 4 +- src/scripts/site.js | 2 - src/scripts/tvlatest.js | 3 +- src/scripts/tvrecommended.js | 4 +- src/serviceworker.js | 2 +- src/tv.html | 6 - 18 files changed, 62 insertions(+), 1150 deletions(-) delete mode 100644 src/components/categorysyncbuttons.js delete mode 100644 src/components/serviceworker/sync.js delete mode 100644 src/components/sync/emby-downloadbutton.js delete mode 100644 src/components/sync/sync.js diff --git a/src/components/categorysyncbuttons.js b/src/components/categorysyncbuttons.js deleted file mode 100644 index 5a6075b196..0000000000 --- a/src/components/categorysyncbuttons.js +++ /dev/null @@ -1,31 +0,0 @@ -define(["itemHelper", "libraryMenu", "apphost"], function(itemHelper, libraryMenu, appHost) { - "use strict"; - - function initSyncButtons(view) { - var apiClient = window.ApiClient; - apiClient && apiClient.getCurrentUserId() && apiClient.getCurrentUser().then(function(user) { - for (var item = { - SupportsSync: !0 - }, categorySyncButtons = view.querySelectorAll(".categorySyncButton"), i = 0, length = categorySyncButtons.length; i < length; i++) categorySyncButtons[i].addEventListener("click", onCategorySyncButtonClick), itemHelper.canSync(user, item) ? categorySyncButtons[i].classList.remove("hide") : categorySyncButtons[i].classList.add("hide") - }) - } - - function onCategorySyncButtonClick(e) { - var button = this, - category = button.getAttribute("data-category"), - parentId = libraryMenu.getTopParentId(); - require(["syncDialog"], function(syncDialog) { - syncDialog.showMenu({ - ParentId: parentId, - Category: category, - serverId: ApiClient.serverId(), - mode: appHost.supports("sync") ? "download" : "sync" - }) - }) - } - return { - init: function(view) { - initSyncButtons(view) - } - } -}); \ No newline at end of file diff --git a/src/components/itemcontextmenu.js b/src/components/itemcontextmenu.js index 270345d3b7..6bc81f62b2 100644 --- a/src/components/itemcontextmenu.js +++ b/src/components/itemcontextmenu.js @@ -118,13 +118,6 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', }); } - if (itemHelper.canConvert(item, user, connectionManager.getApiClient(item))) { - commands.push({ - name: globalize.translate('Convert'), - id: 'convert' - }); - } - if (item.CanDelete && options.deleteItem !== false) { if (item.Type === 'Playlist' || item.Type === 'BoxSet') { @@ -147,15 +140,6 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', }); } - if (appHost.supports('sync') && options.syncLocal !== false) { - if (itemHelper.canSync(user, item)) { - commands.push({ - name: globalize.translate('Download'), - id: 'synclocal' - }); - } - } - var canEdit = itemHelper.canEdit(user, item); if (canEdit) { @@ -328,17 +312,13 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', { require(['fileDownloader'], function (fileDownloader) { var downloadHref = apiClient.getItemDownloadUrl(itemId); - - fileDownloader.download([ - { - url: downloadHref, - itemId: itemId, - serverId: serverId - }]); - + fileDownloader.download([{ + url: downloadHref, + itemId: itemId, + serverId: serverId + }]); getResolveFunction(getResolveFunction(resolve, id), id)(); }); - break; } case 'editsubtitles': @@ -433,102 +413,48 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', break; } case 'share': - { navigator.share({ title: item.Name, text: item.Overview, url: "https://github.com/jellyfin/jellyfin" }); break; - } case 'album': - { - appRouter.showItem(item.AlbumId, item.ServerId); - getResolveFunction(resolve, id)(); - break; - } + appRouter.showItem(item.AlbumId, item.ServerId); + getResolveFunction(resolve, id)(); + break; case 'artist': - { - appRouter.showItem(item.ArtistItems[0].Id, item.ServerId); - getResolveFunction(resolve, id)(); + appRouter.showItem(item.ArtistItems[0].Id, item.ServerId); + getResolveFunction(resolve, id)(); break; - } case 'playallfromhere': - { - getResolveFunction(resolve, id)(); + getResolveFunction(resolve, id)(); break; - } case 'queueallfromhere': { getResolveFunction(resolve, id)(); break; } - case 'convert': - { - require(['syncDialog'], function (syncDialog) { - syncDialog.showMenu({ - items: [item], - serverId: serverId, - mode: 'convert' - }); - }); - getResolveFunction(resolve, id)(); - break; - } - case 'sync': - { - require(['syncDialog'], function (syncDialog) { - syncDialog.showMenu({ - items: [item], - serverId: serverId, - mode: 'sync' - }); - }); - getResolveFunction(resolve, id)(); - break; - } - case 'synclocal': - { - require(['syncDialog'], function (syncDialog) { - syncDialog.showMenu({ - items: [item], - serverId: serverId, - mode: 'download' - }); - }); - getResolveFunction(resolve, id)(); - break; - } case 'removefromplaylist': - apiClient.ajax({ - url: apiClient.getUrl('Playlists/' + options.playlistId + '/Items', { EntryIds: [item.PlaylistItemId].join(',') }), - type: 'DELETE' - }).then(function () { - getResolveFunction(resolve, id, true)(); }); - break; case 'removefromcollection': - apiClient.ajax({ type: "DELETE", url: apiClient.getUrl("Collections/" + options.collectionId + "/Items", { Ids: [item.Id].join(',') }) - }).then(function () { - getResolveFunction(resolve, id, true)(); }); - break; case 'canceltimer': deleteTimer(apiClient, item, resolve, id); diff --git a/src/components/multiselect/multiselect.js b/src/components/multiselect/multiselect.js index 32e3ab9f82..6eace46c7c 100644 --- a/src/components/multiselect/multiselect.js +++ b/src/components/multiselect/multiselect.js @@ -218,13 +218,6 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo }); } - if (user.Policy.EnableContentDownloading && appHost.supports('sync')) { - menuItems.push({ - name: globalize.translate('Download'), - id: 'synclocal' - }); - } - menuItems.push({ name: globalize.translate('GroupVersions'), id: 'groupvideos', @@ -254,20 +247,16 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo } require(['actionsheet'], function (actionsheet) { - actionsheet.show({ items: menuItems, positionTo: e.target, callback: function (id) { - var items = selectedItems.slice(0); var serverId = apiClient.serverInfo().Id; switch (id) { - case 'addtocollection': require(['collectionEditor'], function (collectionEditor) { - new collectionEditor().show({ items: items, serverId: serverId @@ -318,35 +307,6 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo hideSelections(); dispatchNeedsRefresh(); break; - case 'sync': - require(['syncDialog'], function (syncDialog) { - syncDialog.showMenu({ - items: items.map(function (i) { - return { - Id: i - }; - }), - serverId: serverId - }); - }); - hideSelections(); - dispatchNeedsRefresh(); - break; - case 'synclocal': - require(['syncDialog'], function (syncDialog) { - syncDialog.showMenu({ - items: items.map(function (i) { - return { - Id: i - }; - }), - isLocalSync: true, - serverId: serverId - }); - }); - hideSelections(); - dispatchNeedsRefresh(); - break; default: break; } diff --git a/src/components/serviceworker/notifications.js b/src/components/serviceworker/notifications.js index c566715bb7..9c5be840bf 100644 --- a/src/components/serviceworker/notifications.js +++ b/src/components/serviceworker/notifications.js @@ -4,20 +4,14 @@ var connectionManager; function getApiClient(serverId) { - if (connectionManager) { return Promise.resolve(connectionManager.getApiClient(serverId)); } - - //importScripts('serviceworker-cache-polyfill.js'); - return Promise.reject(); } function executeAction(action, data, serverId) { - return getApiClient(serverId).then(function (apiClient) { - switch (action) { case 'cancel-install': var id = data.id; @@ -32,7 +26,6 @@ } self.addEventListener('notificationclick', function (event) { - var notification = event.notification; notification.close(); @@ -47,6 +40,5 @@ } event.waitUntil(executeAction(action, data, serverId)); - }, false); })(); \ No newline at end of file diff --git a/src/components/serviceworker/sync.js b/src/components/serviceworker/sync.js deleted file mode 100644 index 3dcff8f363..0000000000 --- a/src/components/serviceworker/sync.js +++ /dev/null @@ -1,6 +0,0 @@ -self.addEventListener('sync', function (event) { - 'use strict'; - - if (event.tag === 'emby-sync') { - } -}); \ No newline at end of file diff --git a/src/components/sync/emby-downloadbutton.js b/src/components/sync/emby-downloadbutton.js deleted file mode 100644 index 74a9f6b3bb..0000000000 --- a/src/components/sync/emby-downloadbutton.js +++ /dev/null @@ -1,188 +0,0 @@ -define(['connectionManager', 'serverNotifications', 'events', 'globalize', 'emby-button'], function (connectionManager, serverNotifications, events, globalize, EmbyButtonPrototype) { - 'use strict'; - - function onClick(e) { - - var button = this; - var id = button.getAttribute('data-id'); - var serverId = button.getAttribute('data-serverid'); - var apiClient = connectionManager.getApiClient(serverId); - - if (!button.classList.contains('downloadbutton-on')) { - - require(['syncDialog'], function (syncDialog) { - syncDialog.showMenu({ - - items: [id], - mode: 'download', - serverId: serverId - - }).then(function () { - - button.dispatchEvent(new CustomEvent('download', { - cancelable: false - })); - - }); - }); - - } else { - - require(['confirm'], function (confirm) { - - confirm({ - - text: globalize.translate('ConfirmRemoveDownload'), - confirmText: globalize.translate('RemoveDownload'), - cancelText: globalize.translate('KeepDownload'), - primary: 'cancel' - - }).then(function () { - apiClient.cancelSyncItems([id]); - - button.dispatchEvent(new CustomEvent('download-cancel', { - cancelable: false - })); - }); - }); - } - } - - function updateSyncStatus(button, syncPercent) { - - var icon = button.iconElement; - if (!icon) { - button.iconElement = button.querySelector('i'); - icon = button.iconElement; - } - - if (syncPercent != null) { - button.classList.add('downloadbutton-on'); - - if (icon) { - icon.classList.add('downloadbutton-icon-on'); - } - - } else { - button.classList.remove('downloadbutton-on'); - - if (icon) { - icon.classList.remove('downloadbutton-icon-on'); - } - } - - if ((syncPercent || 0) >= 100) { - button.classList.add('downloadbutton-complete'); - - if (icon) { - icon.classList.add('downloadbutton-icon-complete'); - } - } else { - button.classList.remove('downloadbutton-complete'); - - if (icon) { - icon.classList.remove('downloadbutton-icon-complete'); - } - } - - var text; - if ((syncPercent || 0) >= 100) { - text = globalize.translate('Downloaded'); - } else if (syncPercent != null) { - text = globalize.translate('Downloading'); - } else { - text = globalize.translate('Download'); - } - - var textElement = button.querySelector('.emby-downloadbutton-downloadtext'); - if (textElement) { - textElement.innerHTML = text; - } - - button.title = text; - } - - function clearEvents(button) { - - button.removeEventListener('click', onClick); - } - - function bindEvents(button) { - - clearEvents(button); - - button.addEventListener('click', onClick); - } - - var EmbyDownloadButtonPrototype = Object.create(EmbyButtonPrototype); - - EmbyDownloadButtonPrototype.createdCallback = function () { - - // base method - if (EmbyButtonPrototype.createdCallback) { - EmbyButtonPrototype.createdCallback.call(this); - } - }; - - EmbyDownloadButtonPrototype.attachedCallback = function () { - - // base method - if (EmbyButtonPrototype.attachedCallback) { - EmbyButtonPrototype.attachedCallback.call(this); - } - - var itemId = this.getAttribute('data-id'); - var serverId = this.getAttribute('data-serverid'); - if (itemId && serverId) { - - bindEvents(this); - } - }; - - EmbyDownloadButtonPrototype.detachedCallback = function () { - - // base method - if (EmbyButtonPrototype.detachedCallback) { - EmbyButtonPrototype.detachedCallback.call(this); - } - - clearEvents(this); - - this.iconElement = null; - }; - - function fetchAndUpdate(button, item) { - - connectionManager.getApiClient(item.ServerId).getSyncStatus(item.Id).then(function (result) { - - updateSyncStatus(button, result.Progress); - - }, function () { - - }); - } - - EmbyDownloadButtonPrototype.setItem = function (item) { - - if (item) { - - this.setAttribute('data-id', item.Id); - this.setAttribute('data-serverid', item.ServerId); - - fetchAndUpdate(this, item); - - bindEvents(this); - - } else { - - this.removeAttribute('data-id'); - this.removeAttribute('data-serverid'); - clearEvents(this); - } - }; - - document.registerElement('emby-downloadbutton', { - prototype: EmbyDownloadButtonPrototype, - extends: 'button' - }); -}); \ No newline at end of file diff --git a/src/components/sync/sync.js b/src/components/sync/sync.js deleted file mode 100644 index e7c51e3dc5..0000000000 --- a/src/components/sync/sync.js +++ /dev/null @@ -1,736 +0,0 @@ -define(['apphost', 'globalize', 'connectionManager', 'layoutManager', 'focusManager', 'scrollHelper', 'appSettings', 'registrationServices', 'dialogHelper', 'paper-icon-button-light', 'formDialogStyle'], function (appHost, globalize, connectionManager, layoutManager, focusManager, scrollHelper, appSettings, registrationServices, dialogHelper) { - 'use strict'; - - var currentDialogOptions; - - function submitJob(dlg, apiClient, userId, syncOptions, form) { - - if (!userId) { - throw new Error('userId cannot be null'); - } - - if (!syncOptions) { - throw new Error('syncOptions cannot be null'); - } - - if (!form) { - throw new Error('form cannot be null'); - } - - var selectSyncTarget = form.querySelector('#selectSyncTarget'); - var target = selectSyncTarget ? selectSyncTarget.value : null; - - if (!target) { - - require(['toast'], function (toast) { - toast(globalize.translate('PleaseSelectDeviceToSyncTo')); - }); - return false; - } - - var options = { - - userId: userId, - TargetId: target, - - ParentId: syncOptions.ParentId, - Category: syncOptions.Category - }; - - setJobValues(options, form); - - if (syncOptions.items && syncOptions.items.length) { - options.ItemIds = (syncOptions.items || []).map(function (i) { - return i.Id || i; - }).join(','); - } - - apiClient.ajax({ - - type: "POST", - url: apiClient.getUrl("Sync/Jobs"), - data: JSON.stringify(options), - contentType: "application/json", - dataType: 'json' - - }).then(function () { - - dialogHelper.close(dlg); - require(['toast'], function (toast) { - - showSubmissionToast(target, apiClient); - - if (syncOptions.mode === 'download') { - syncNow(); - } - }); - }); - - return true; - } - - - function showSubmissionToast(targetId, apiClient) { - - require(['toast'], function (toast) { - - var msg = targetId === apiClient.deviceId() ? - globalize.translate('DownloadingDots') : - globalize.translate('SyncingDots'); - - toast(msg); - }); - } - - function syncNow() { - require(['localsync'], function (localSync) { - localSync.sync(); - }); - } - - function submitQuickSyncJob(apiClient, userId, targetId, syncOptions) { - - if (!userId) { - throw new Error('userId cannot be null'); - } - - if (!syncOptions) { - throw new Error('syncOptions cannot be null'); - } - - if (!targetId) { - throw new Error('targetId cannot be null'); - } - - var options = { - - userId: userId, - TargetId: targetId, - - ParentId: syncOptions.ParentId, - Category: syncOptions.Category, - Quality: syncOptions.Quality, - Bitrate: syncOptions.Bitrate - }; - - if (syncOptions.items && syncOptions.items.length) { - options.ItemIds = (syncOptions.items || []).map(function (i) { - return i.Id || i; - }).join(','); - } - - return apiClient.ajax({ - - type: "POST", - url: apiClient.getUrl("Sync/Jobs"), - data: JSON.stringify(options), - contentType: "application/json", - dataType: 'json' - - }).then(function () { - - require(['toast'], function (toast) { - - showSubmissionToast(targetId, apiClient); - - if (syncOptions.mode === 'download') { - syncNow(); - } - }); - }); - } - - function setJobValues(job, form) { - - var txtBitrate = form.querySelector('#txtBitrate'); - var bitrate = txtBitrate ? txtBitrate.value : null; - - if (bitrate) { - bitrate = parseFloat(bitrate) * 1000000; - } - job.Bitrate = bitrate; - - var selectQuality = form.querySelector('#selectQuality'); - if (selectQuality) { - job.Quality = selectQuality.value; - - appSettings.set('sync-lastquality', job.Quality || ''); - } - - var selectProfile = form.querySelector('#selectProfile'); - if (selectProfile) { - job.Profile = selectProfile.value; - } - - var txtItemLimit = form.querySelector('#txtItemLimit'); - if (txtItemLimit) { - job.ItemLimit = txtItemLimit.value || null; - } - - var chkSyncNewContent = form.querySelector('#chkSyncNewContent'); - if (chkSyncNewContent) { - job.SyncNewContent = chkSyncNewContent.checked; - } - - var chkUnwatchedOnly = form.querySelector('#chkUnwatchedOnly'); - if (chkUnwatchedOnly) { - job.UnwatchedOnly = chkUnwatchedOnly.checked; - } - } - - function renderForm(options) { - - return new Promise(function (resolve, reject) { - - require(['emby-checkbox', 'emby-input', 'emby-select'], function () { - - renderFormInternal(options, connectionManager.deviceId(), resolve); - }); - }); - } - - function renderFormInternal(options, defaultTargetId, resolve) { - - var elem = options.elem; - var dialogOptions = options.dialogOptions; - - var targets = dialogOptions.Targets; - - var html = ''; - - var mode = options.mode; - var targetContainerClass = mode === 'download' ? ' hide' : ''; - - var syncTargetLabel = mode === 'convert' ? globalize.translate('LabelConvertTo') : globalize.translate('LabelSyncTo'); - - if (options.readOnlySyncTarget) { - html += '
'; - html += ''; - html += '
'; - } else { - html += '
'; - html += ''; - if (!targets.length) { - html += '
' + globalize.translate('LabelSyncNoTargetsHelp') + '
'; - } - - if (appHost.supports('externallinks')) { - html += ''; - } - html += '
'; - } - - html += '
'; - html += ''; - html += '
'; - html += '
'; - - html += '
'; - html += ''; - html += '
'; - html += '
'; - - html += '
'; - html += ''; - html += '
'; - - if (dialogOptions.Options.indexOf('UnwatchedOnly') !== -1) { - html += '
'; - html += ''; - - if (mode === 'convert') { - html += '
' + globalize.translate('ConvertUnwatchedVideosOnlyHelp') + '
'; - } else { - html += '
' + globalize.translate('SyncUnwatchedVideosOnlyHelp') + '
'; - } - - html += '
'; - } - - if (dialogOptions.Options.indexOf('SyncNewContent') !== -1) { - html += '
'; - html += ''; - - if (mode === 'convert') { - html += '
' + globalize.translate('AutomaticallyConvertNewContentHelp') + '
'; - } else { - html += '
' + globalize.translate('AutomaticallySyncNewContentHelp') + '
'; - } - html += '
'; - } - - if (dialogOptions.Options.indexOf('ItemLimit') !== -1) { - html += '
'; - html += ''; - - if (mode === 'convert') { - html += '
' + globalize.translate('ConvertItemLimitHelp') + '
'; - } else { - html += '
' + globalize.translate('DownloadItemLimitHelp') + '
'; - } - - html += '
'; - } - - //html += '
'; - //html += '
'; - - elem.innerHTML = html; - - var selectSyncTarget = elem.querySelector('#selectSyncTarget'); - if (selectSyncTarget) { - selectSyncTarget.addEventListener('change', function () { - loadQualityOptions(elem, this.value, options.dialogOptionsFn).then(resolve); - }); - selectSyncTarget.dispatchEvent(new CustomEvent('change', { - bubbles: true - })); - } - - var selectProfile = elem.querySelector('#selectProfile'); - if (selectProfile) { - selectProfile.addEventListener('change', function () { - onProfileChange(elem, this.value); - }); - - if (dialogOptions.ProfileOptions.length) { - selectProfile.dispatchEvent(new CustomEvent('change', { - bubbles: true - })); - } - } - - var selectQuality = elem.querySelector('#selectQuality'); - if (selectQuality) { - selectQuality.addEventListener('change', function () { - onQualityChange(elem, this.value); - }); - selectQuality.dispatchEvent(new CustomEvent('change', { - bubbles: true - })); - } - - // This isn't ideal, but allow time for the change handlers above to run - setTimeout(function () { - focusManager.autoFocus(elem); - }, 100); - } - - function showWifiMessage() { - - require(['dialog', 'appRouter'], function (dialog, appRouter) { - - var options = { - - title: globalize.translate('HeaderWaitingForWifi'), - text: globalize.translate('WifiRequiredToDownload') - }; - - var items = []; - - items.push({ - name: options.confirmText || globalize.translate('ButtonOk'), - id: 'ok', - type: 'submit' - }); - - items.push({ - name: options.cancelText || globalize.translate('HeaderDownloadSettings'), - id: 'downloadsettings', - type: 'cancel' - }); - - options.buttons = items; - - dialog(options).then(function (result) { - - if (result === 'ok') { - return Promise.resolve(); - } - if (result === 'downloadsettings') { - appRouter.show(appRouter.getRouteUrl('downloadsettings')); - return Promise.resolve(); - } - - return Promise.reject(); - }); - }); - } - - function validateNetwork() { - - var network = navigator.connection ? navigator.connection.type : null; - - switch (network) { - - case 'cellular': - case 'bluetooth': - showWifiMessage(); - return false; - default: - return true; - } - } - - function showSyncMenu(options) { - - if (options.mode === 'download' && appSettings.syncOnlyOnWifi() && !validateNetwork()) { - return Promise.reject(); - } - - return registrationServices.validateFeature('sync').then(function () { - return showSyncMenuInternal(options); - }); - } - - function enableAutoSync(options) { - - if (options.mode !== 'download') { - return false; - } - - var firstItem = (options.items || [])[0] || {}; - - if (firstItem.Type === 'Audio') { - return true; - } - if (firstItem.Type === 'MusicAlbum') { - return true; - } - if (firstItem.Type === 'MusicArtist') { - return true; - } - if (firstItem.Type === 'MusicGenre') { - return true; - } - if (firstItem.Type === 'Playlist' && firstItem.MediaType === 'Audio') { - return true; - } - - return false; - } - - function showSyncMenuInternal(options) { - - var apiClient = connectionManager.getApiClient(options.serverId); - var userId = apiClient.getCurrentUserId(); - - if (enableAutoSync(options)) { - - return submitQuickSyncJob(apiClient, userId, apiClient.deviceId(), { - items: options.items, - Quality: 'custom', - Bitrate: appSettings.maxStaticMusicBitrate() - }); - } - - var dialogOptionsFn = getTargetDialogOptionsFn(apiClient, { - UserId: userId, - ItemIds: (options.items || []).map(function (i) { - return i.Id || i; - }).join(','), - - ParentId: options.ParentId, - Category: options.Category, - IncludeProviders: options.mode === 'convert' ? 'ConvertSyncProvider' : null, - ExcludeProviders: options.mode === 'convert' ? null : 'ConvertSyncProvider' - }); - - return dialogOptionsFn().then(function (dialogOptions) { - - currentDialogOptions = dialogOptions; - - var dlgElementOptions = { - removeOnClose: true, - scrollY: false, - autoFocus: false - }; - - if (layoutManager.tv) { - dlgElementOptions.size = 'fullscreen'; - } else { - dlgElementOptions.size = 'small'; - } - - var dlg = dialogHelper.createDialog(dlgElementOptions); - - dlg.classList.add('formDialog'); - - var html = ''; - html += '
'; - html += ''; - html += '

'; - - var syncButtonLabel = options.mode === 'download' ? - globalize.translate('Download') : - (options.mode === 'convert' ? globalize.translate('Convert') : globalize.translate('Sync')); - - html += syncButtonLabel; - html += '

'; - - if (appHost.supports('externallinks')) { - html += 'info' + globalize.translate('Help') + ''; - } - - html += '
'; - - html += '
'; - html += '
'; - - html += '
'; - - html += '
'; - - html += '
'; - - html += ''; - html += '
'; - - html += '
'; - - html += '
'; - html += '
'; - - dlg.innerHTML = html; - - var submitted = false; - - dlg.querySelector('form').addEventListener('submit', function (e) { - - submitted = submitJob(dlg, apiClient, userId, options, this); - - e.preventDefault(); - return false; - }); - - dlg.querySelector('.btnCancel').addEventListener('click', function () { - dialogHelper.close(dlg); - }); - - if (layoutManager.tv) { - scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false); - } - - var promise = dialogHelper.open(dlg); - - renderForm({ - elem: dlg.querySelector('.formFields'), - dialogOptions: dialogOptions, - dialogOptionsFn: dialogOptionsFn, - mode: options.mode - }); - - return promise.then(function () { - if (layoutManager.tv) { - scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false); - } - - if (submitted) { - return Promise.resolve(); - } - return Promise.reject(); - }); - }); - } - - function getTargetDialogOptionsFn(apiClient, query) { - - return function (targetId) { - - query.TargetId = targetId; - return apiClient.getJSON(apiClient.getUrl('Sync/Options', query)); - }; - } - - function setQualityFieldVisible(form, visible) { - - var fldQuality = form.querySelector('.fldQuality'); - var selectQuality = form.querySelector('#selectQuality'); - - if (visible) { - if (fldQuality) { - fldQuality.classList.remove('hide'); - } - if (selectQuality) { - //selectQuality.setAttribute('required', 'required'); - - // This is a hack due to what appears to be a edge bug but it shoudln't matter as the list always has selectable items - selectQuality.removeAttribute('required'); - } - } else { - if (fldQuality) { - fldQuality.classList.add('hide'); - } - if (selectQuality) { - selectQuality.removeAttribute('required'); - } - } - } - - function onProfileChange(form, profileId) { - - var options = currentDialogOptions || {}; - - var profileOptions = options.ProfileOptions || []; - - if (!profileOptions.length) { - return; - } - - var option = profileOptions.filter(function (o) { - return o.Id === profileId; - })[0]; - - var qualityOptions = options.QualityOptions || []; - - if (option) { - form.querySelector('.profileDescription').innerHTML = option.Description || ''; - setQualityFieldVisible(form, qualityOptions.length > 0 && option.EnableQualityOptions && options.Options.indexOf('Quality') !== -1); - } else { - form.querySelector('.profileDescription').innerHTML = ''; - setQualityFieldVisible(form, qualityOptions.length > 0 && options.Options.indexOf('Quality') !== -1); - } - } - - function onQualityChange(form, qualityId) { - - var options = currentDialogOptions || {}; - var option = (options.QualityOptions || []).filter(function (o) { - return o.Id === qualityId; - })[0]; - - var qualityDescription = form.querySelector('.qualityDescription'); - - if (option) { - qualityDescription.innerHTML = option.Description || ''; - } else { - qualityDescription.innerHTML = ''; - } - - var fldBitrate = form.querySelector('.fldBitrate'); - var txtBitrate = form.querySelector('#txtBitrate'); - - if (qualityId === 'custom') { - - if (fldBitrate) { - fldBitrate.classList.remove('hide'); - } - if (txtBitrate) { - txtBitrate.setAttribute('required', 'required'); - } - } else { - if (fldBitrate) { - fldBitrate.classList.add('hide'); - } - if (txtBitrate) { - txtBitrate.removeAttribute('required'); - } - } - } - - function renderTargetDialogOptions(form, options) { - - currentDialogOptions = options; - - var fldProfile = form.querySelector('.fldProfile'); - var selectProfile = form.querySelector('#selectProfile'); - - if (options.ProfileOptions.length && options.Options.indexOf('Profile') !== -1) { - if (fldProfile) { - fldProfile.classList.remove('hide'); - } - if (selectProfile) { - selectProfile.setAttribute('required', 'required'); - } - } else { - if (fldProfile) { - fldProfile.classList.add('hide'); - } - if (selectProfile) { - selectProfile.removeAttribute('required'); - } - } - - setQualityFieldVisible(form, options.QualityOptions.length > 0); - - if (selectProfile) { - selectProfile.innerHTML = options.ProfileOptions.map(function (o) { - - var selectedAttribute = o.IsDefault ? ' selected="selected"' : ''; - return ''; - - }).join(''); - - selectProfile.dispatchEvent(new CustomEvent('change', { - bubbles: true - })); - } - - var selectQuality = form.querySelector('#selectQuality'); - if (selectQuality) { - selectQuality.innerHTML = options.QualityOptions.map(function (o) { - - var selectedAttribute = o.IsDefault ? ' selected="selected"' : ''; - return ''; - - }).join(''); - - var lastQuality = appSettings.get('sync-lastquality'); - if (lastQuality && options.QualityOptions.filter(function (i) { - - return i.Id === lastQuality; - - }).length) { - selectQuality.value = lastQuality; - } - - selectQuality.dispatchEvent(new CustomEvent('change', { - bubbles: true - })); - } - } - - function loadQualityOptions(form, targetId, dialogOptionsFn) { - - return dialogOptionsFn(targetId).then(function (options) { - - return renderTargetDialogOptions(form, options); - }); - } - - return { - - showMenu: showSyncMenu, - renderForm: renderForm, - setJobValues: setJobValues - }; -}); \ No newline at end of file diff --git a/src/itemdetails.html b/src/itemdetails.html index cf9433583b..30d6171f43 100644 --- a/src/itemdetails.html +++ b/src/itemdetails.html @@ -104,18 +104,6 @@ ${ButtonShuffle} - - - - - -
diff --git a/src/movies.html b/src/movies.html index 4830d6408a..c211d9686a 100644 --- a/src/movies.html +++ b/src/movies.html @@ -30,9 +30,6 @@

${HeaderLatestMovies}

-
diff --git a/src/scripts/itemdetailpage.js b/src/scripts/itemdetailpage.js index d8d952cba0..ba1bac9e24 100644 --- a/src/scripts/itemdetailpage.js +++ b/src/scripts/itemdetailpage.js @@ -1,4 +1,4 @@ -define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuilder", "datetime", "mediaInfo", "backdrop", "listView", "itemContextMenu", "itemHelper", "dom", "indicators", "apphost", "imageLoader", "libraryMenu", "globalize", "browser", "events", "scrollHelper", "playbackManager", "libraryBrowser", "scrollStyles", "emby-itemscontainer", "emby-checkbox", "emby-linkbutton", "emby-playstatebutton", "emby-ratingbutton", "emby-downloadbutton", "emby-scroller", "emby-select"], function(loading, appRouter, layoutManager, connectionManager, cardBuilder, datetime, mediaInfo, backdrop, listView, itemContextMenu, itemHelper, dom, indicators, appHost, imageLoader, libraryMenu, globalize, browser, events, scrollHelper, playbackManager, libraryBrowser) { +define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuilder", "datetime", "mediaInfo", "backdrop", "listView", "itemContextMenu", "itemHelper", "dom", "indicators", "apphost", "imageLoader", "libraryMenu", "globalize", "browser", "events", "scrollHelper", "playbackManager", "libraryBrowser", "scrollStyles", "emby-itemscontainer", "emby-checkbox", "emby-linkbutton", "emby-playstatebutton", "emby-ratingbutton", "emby-scroller", "emby-select"], function(loading, appRouter, layoutManager, connectionManager, cardBuilder, datetime, mediaInfo, backdrop, listView, itemContextMenu, itemHelper, dom, indicators, appHost, imageLoader, libraryMenu, globalize, browser, events, scrollHelper, playbackManager, libraryBrowser) { "use strict"; function getPromise(apiClient, params) { @@ -33,12 +33,7 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild user: user, share: !0 }; - return appHost.supports("sync") && (options.syncLocal = !1), options - } - - function renderSyncLocalContainer(page, params, user, item) { - if (appHost.supports("sync")) - for (var canSync = itemHelper.canSync(user, item), buttons = page.querySelectorAll(".btnSyncDownload"), i = 0, length = buttons.length; i < length; i++) buttons[i].setItem(item), canSync ? buttons[i].classList.remove("hide") : buttons[i].classList.add("hide") + return options; } function getProgramScheduleHtml(items, options) { @@ -286,7 +281,11 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild var apiClient = connectionManager.getApiClient(item.ServerId); renderSeriesTimerEditor(page, item, apiClient, user), renderTimerEditor(page, item, apiClient, user), renderImage(page, item, apiClient, user), renderLogo(page, item, apiClient), setTitle(item, apiClient), setInitialCollapsibleState(page, item, apiClient, context, user), renderDetails(page, item, apiClient, context), renderTrackSelections(page, instance, item), dom.getWindowSize().innerWidth >= 1e3 ? backdrop.setBackdrops([item]) : backdrop.clear(), renderDetailPageBackdrop(page, item, apiClient); var canPlay = reloadPlayButtons(page, item); - (item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && -1 !== playbackManager.getSupportedCommands().indexOf("PlayTrailers") ? hideAll(page, "btnPlayTrailer", !0) : hideAll(page, "btnPlayTrailer"), setTrailerButtonVisibility(page, item), item.CanDelete && !item.IsFolder ? hideAll(page, "btnDeleteItem", !0) : hideAll(page, "btnDeleteItem"), renderSyncLocalContainer(page, params, user, item), "Program" !== item.Type || canPlay ? hideAll(page, "mainDetailButtons", !0) : hideAll(page, "mainDetailButtons"), showRecordingFields(instance, page, item, user); + (item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && -1 !== playbackManager.getSupportedCommands().indexOf("PlayTrailers") ? hideAll(page, "btnPlayTrailer", !0) : hideAll(page, "btnPlayTrailer"); + setTrailerButtonVisibility(page, item); + item.CanDelete && !item.IsFolder ? hideAll(page, "btnDeleteItem", !0) : hideAll(page, "btnDeleteItem"); + "Program" !== item.Type || canPlay ? hideAll(page, "mainDetailButtons", !0) : hideAll(page, "mainDetailButtons"); + showRecordingFields(instance, page, item, user); var groupedVersions = (item.MediaSources || []).filter(function(g) { return "Grouping" == g.Type }); @@ -1166,30 +1165,55 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild })) } } - var currentItem, self = this, - apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient; + + var currentItem; + var self = this; + var apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient; view.querySelectorAll(".btnPlay"); - bindAll(view, ".btnPlay", "click", onPlayClick), bindAll(view, ".btnResume", "click", onPlayClick), bindAll(view, ".btnInstantMix", "click", onInstantMixClick), bindAll(view, ".btnShuffle", "click", onShuffleClick), bindAll(view, ".btnPlayTrailer", "click", onPlayTrailerClick), bindAll(view, ".btnCancelSeriesTimer", "click", onCancelSeriesTimerClick), bindAll(view, ".btnCancelTimer", "click", onCancelTimerClick), bindAll(view, ".btnDeleteItem", "click", onDeleteClick), bindAll(view, ".btnSyncDownload", "download", onDownloadChange), bindAll(view, ".btnSyncDownload", "download-cancel", onDownloadChange), view.querySelector(".btnMoreCommands i").innerHTML = "", view.querySelector(".trackSelections").addEventListener("submit", onTrackSelectionsSubmit), view.querySelector(".btnSplitVersions").addEventListener("click", function() { + bindAll(view, ".btnPlay", "click", onPlayClick); + bindAll(view, ".btnResume", "click", onPlayClick); + bindAll(view, ".btnInstantMix", "click", onInstantMixClick); + bindAll(view, ".btnShuffle", "click", onShuffleClick); + bindAll(view, ".btnPlayTrailer", "click", onPlayTrailerClick); + bindAll(view, ".btnCancelSeriesTimer", "click", onCancelSeriesTimerClick); + bindAll(view, ".btnCancelTimer", "click", onCancelTimerClick); + bindAll(view, ".btnDeleteItem", "click", onDeleteClick); + view.querySelector(".btnMoreCommands i").innerHTML = ""; + view.querySelector(".trackSelections").addEventListener("submit", onTrackSelectionsSubmit); + view.querySelector(".btnSplitVersions").addEventListener("click", function() { splitVersions(self, view, apiClient, params) - }), bindAll(view, ".btnMoreCommands", "click", onMoreCommandsClick), view.querySelector(".selectSource").addEventListener("change", function() { - renderVideoSelections(view, self._currentPlaybackMediaSources), renderAudioSelections(view, self._currentPlaybackMediaSources), renderSubtitleSelections(view, self._currentPlaybackMediaSources) - }), view.addEventListener("click", function(e) { + }); + bindAll(view, ".btnMoreCommands", "click", onMoreCommandsClick); + view.querySelector(".selectSource").addEventListener("change", function() { + renderVideoSelections(view, self._currentPlaybackMediaSources); + renderAudioSelections(view, self._currentPlaybackMediaSources); + renderSubtitleSelections(view, self._currentPlaybackMediaSources); + }); + view.addEventListener("click", function(e) { dom.parentWithClass(e.target, "moreScenes") ? apiClient.getCurrentUser().then(function(user) { renderScenes(view, currentItem) }) : dom.parentWithClass(e.target, "morePeople") ? renderCast(view, currentItem, params.context) : dom.parentWithClass(e.target, "moreSpecials") && apiClient.getCurrentUser().then(function(user) { renderSpecials(view, currentItem, user) }) - }), view.querySelector(".detailImageContainer").addEventListener("click", function(e) { + }); + view.querySelector(".detailImageContainer").addEventListener("click", function(e) { dom.parentWithClass(e.target, "itemDetailGalleryLink") && editImages().then(function() { reload(self, view, params) }) - }), view.addEventListener("viewshow", function(e) { + }); + view.addEventListener("viewshow", function(e) { var page = this; libraryMenu.setTransparentMenu(!0), e.detail.isRestored ? currentItem && (setTitle(currentItem, connectionManager.getApiClient(currentItem.ServerId)), renderTrackSelections(page, self, currentItem, !0)) : reload(self, page, params), events.on(apiClient, "message", onWebSocketMessage), events.on(playbackManager, "playerchange", onPlayerChange) - }), view.addEventListener("viewbeforehide", function() { - events.off(apiClient, "message", onWebSocketMessage), events.off(playbackManager, "playerchange", onPlayerChange), libraryMenu.setTransparentMenu(!1) - }), view.addEventListener("viewdestroy", function() { - currentItem = null, self._currentPlaybackMediaSources = null, self.currentRecordingFields = null + }); + view.addEventListener("viewbeforehide", function() { + events.off(apiClient, "message", onWebSocketMessage); + events.off(playbackManager, "playerchange", onPlayerChange); + libraryMenu.setTransparentMenu(!1); + }); + view.addEventListener("viewdestroy", function() { + currentItem = null; + self._currentPlaybackMediaSources = null; + self.currentRecordingFields = null; }) } }); diff --git a/src/scripts/livetvrecordings.js b/src/scripts/livetvrecordings.js index 6c0ee4e515..c56956314d 100644 --- a/src/scripts/livetvrecordings.js +++ b/src/scripts/livetvrecordings.js @@ -1,4 +1,4 @@ -define(["layoutManager", "loading", "components/categorysyncbuttons", "cardBuilder", "apphost", "imageLoader", "scripts/livetvcomponents", "listViewStyle", "emby-itemscontainer"], function(layoutManager, loading, categorysyncbuttons, cardBuilder, appHost, imageLoader) { +define(["layoutManager", "loading", "cardBuilder", "apphost", "imageLoader", "scripts/livetvcomponents", "listViewStyle", "emby-itemscontainer"], function(layoutManager, loading, cardBuilder, appHost, imageLoader) { "use strict"; function renderRecordings(elem, recordings, cardOptions, scrollX) { @@ -54,7 +54,6 @@ define(["layoutManager", "loading", "components/categorysyncbuttons", "cardBuild } var foldersPromise, latestPromise, self = this, lastFullRender = 0; - categorysyncbuttons.init(tabContent); for (var moreButtons = tabContent.querySelectorAll(".more"), i = 0, length = moreButtons.length; i < length; i++) moreButtons[i].addEventListener("click", onMoreClick); self.preRender = function() { enableFullRender() && (latestPromise = ApiClient.getLiveTvRecordings({ diff --git a/src/scripts/moviesrecommended.js b/src/scripts/moviesrecommended.js index 31c9bfba47..9f0379861f 100644 --- a/src/scripts/moviesrecommended.js +++ b/src/scripts/moviesrecommended.js @@ -1,4 +1,4 @@ -define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu", "mainTabsManager", "components/categorysyncbuttons", "cardBuilder", "dom", "imageLoader", "playbackManager", "emby-itemscontainer", "emby-tabs", "emby-button"], function(events, layoutManager, inputManager, userSettings, libraryMenu, mainTabsManager, categorysyncbuttons, cardBuilder, dom, imageLoader, playbackManager) { +define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu", "mainTabsManager", "cardBuilder", "dom", "imageLoader", "playbackManager", "emby-itemscontainer", "emby-tabs", "emby-button"], function(events, layoutManager, inputManager, userSettings, libraryMenu, mainTabsManager, cardBuilder, dom, imageLoader, playbackManager) { "use strict"; function enableScrollX() { @@ -250,7 +250,7 @@ define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu" suggestionsTabIndex = 1; self.initTab = function() { var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); - categorysyncbuttons.init(tabContent), initSuggestedTab(view, tabContent) + initSuggestedTab(view, tabContent); }, self.renderTab = function() { var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); loadSuggestionsTab(view, params, tabContent) diff --git a/src/scripts/site.js b/src/scripts/site.js index c9b1e7fee8..7eef9f3809 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -1431,7 +1431,6 @@ var AppInfo = {}; define("programStyles", ["css!" + componentsPath + "/guide/programs"], returnFirstDependency); define("guide-settings-dialog", [componentsPath + "/guide/guide-settings"], returnFirstDependency); define("loadingDialog", [componentsPath + "/loadingdialog/loadingdialog"], returnFirstDependency); - define("syncDialog", [componentsPath + "/sync/sync"], returnFirstDependency); define("viewManager", [componentsPath + "/viewmanager/viewmanager"], function (viewManager) { window.ViewManager = viewManager; viewManager.dispatchPageEvents(true); @@ -1470,7 +1469,6 @@ var AppInfo = {}; define("userdataButtons", [componentsPath + "/userdatabuttons/userdatabuttons"], returnFirstDependency); define("emby-playstatebutton", [componentsPath + "/userdatabuttons/emby-playstatebutton"], returnFirstDependency); define("emby-ratingbutton", [componentsPath + "/userdatabuttons/emby-ratingbutton"], returnFirstDependency); - define("emby-downloadbutton", [componentsPath + "/sync/emby-downloadbutton"], returnFirstDependency); define("listView", [componentsPath + "/listview/listview"], returnFirstDependency); define("listViewStyle", ["css!" + componentsPath + "/listview/listview"], returnFirstDependency); define("formDialogStyle", ["css!" + componentsPath + "/formdialog"], returnFirstDependency); diff --git a/src/scripts/tvlatest.js b/src/scripts/tvlatest.js index a3cebdd8ee..2f0c4a51aa 100644 --- a/src/scripts/tvlatest.js +++ b/src/scripts/tvlatest.js @@ -1,4 +1,4 @@ -define(["loading", "components/categorysyncbuttons", "components/groupedcards", "cardBuilder", "apphost", "imageLoader"], function(loading, categorysyncbuttons, groupedcards, cardBuilder, appHost, imageLoader) { +define(["loading", "components/groupedcards", "cardBuilder", "apphost", "imageLoader"], function(loading, groupedcards, cardBuilder, appHost, imageLoader) { "use strict"; function getLatestPromise(context, params) { @@ -43,7 +43,6 @@ define(["loading", "components/categorysyncbuttons", "components/groupedcards", } return function(view, params, tabContent) { var self = this; - categorysyncbuttons.init(tabContent); var latestPromise; self.preRender = function() { latestPromise = getLatestPromise(view, params) diff --git a/src/scripts/tvrecommended.js b/src/scripts/tvrecommended.js index 12fbd9081b..c575232831 100644 --- a/src/scripts/tvrecommended.js +++ b/src/scripts/tvrecommended.js @@ -1,4 +1,4 @@ -define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "dom", "components/categorysyncbuttons", "userSettings", "cardBuilder", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-button"], function(events, inputManager, libraryMenu, layoutManager, loading, dom, categorysyncbuttons, userSettings, cardBuilder, playbackManager, mainTabsManager) { +define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "dom", "userSettings", "cardBuilder", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-button"], function(events, inputManager, libraryMenu, layoutManager, loading, dom, userSettings, cardBuilder, playbackManager, mainTabsManager) { "use strict"; function getTabs() { @@ -204,7 +204,7 @@ define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "do initialTabIndex = currentTabIndex; self.initTab = function() { var tabContent = self.tabContent; - setScrollClasses(tabContent.querySelector("#resumableItems"), enableScrollX()), categorysyncbuttons.init(tabContent) + setScrollClasses(tabContent.querySelector("#resumableItems"), enableScrollX()) }, self.renderTab = function() { reload() }; diff --git a/src/serviceworker.js b/src/serviceworker.js index 01cf8d63ef..4d9e12ee6a 100644 --- a/src/serviceworker.js +++ b/src/serviceworker.js @@ -1 +1 @@ -importScripts("components/serviceworker/notifications.js", "components/serviceworker/sync.js"); \ No newline at end of file +importScripts("components/serviceworker/notifications.js"); \ No newline at end of file diff --git a/src/tv.html b/src/tv.html index fe95338af3..2a8c3ade26 100644 --- a/src/tv.html +++ b/src/tv.html @@ -30,9 +30,6 @@

${HeaderNextUp}

-
@@ -43,9 +40,6 @@

${HeaderLatestEpisodes}

-
From 65fafe9c58dcd6d6785d325fbf78d4117c2d608e Mon Sep 17 00:00:00 2001 From: dkanada Date: Tue, 19 Mar 2019 17:03:11 -0700 Subject: [PATCH 122/220] remove registration services --- src/components/emby-button/emby-button.js | 16 +-- src/components/homesections/homesections.js | 91 +--------------- .../playback/playaccessvalidation.js | 6 - src/components/playback/playbackvalidation.js | 80 -------------- .../recordingcreator/recordingbutton.js | 2 +- .../recordingcreator/recordingfields.js | 103 +----------------- .../recordingfields.template.html | 12 -- .../recordingcreator/recordinghelper.js | 43 +++----- .../registrationservices.js | 16 --- src/components/skinmanager.js | 52 +-------- src/scripts/site.js | 2 - 11 files changed, 30 insertions(+), 393 deletions(-) delete mode 100644 src/components/playback/playbackvalidation.js delete mode 100644 src/components/registrationservices/registrationservices.js diff --git a/src/components/emby-button/emby-button.js b/src/components/emby-button/emby-button.js index 99a6aea925..d80b224d03 100644 --- a/src/components/emby-button/emby-button.js +++ b/src/components/emby-button/emby-button.js @@ -4,25 +4,11 @@ define(['browser', 'dom', 'layoutManager', 'shell', 'appRouter', 'apphost', 'css var EmbyButtonPrototype = Object.create(HTMLButtonElement.prototype); var EmbyLinkButtonPrototype = Object.create(HTMLAnchorElement.prototype); - function openPremiumInfo() { - - require(['registrationServices'], function (registrationServices) { - registrationServices.showPremiereInfo(); - }); - } - function onAnchorClick(e) { - var href = this.getAttribute('href') || ''; - if (href !== '#') { - if (this.getAttribute('target')) { - if (href.indexOf('emby.media/premiere') !== -1 && !appHost.supports('externalpremium')) { - e.preventDefault(); - openPremiumInfo(); - } - else if (!appHost.supports('targetblank')) { + if (!appHost.supports('targetblank')) { e.preventDefault(); shell.openUrl(href); } diff --git a/src/components/homesections/homesections.js b/src/components/homesections/homesections.js index 82f6041c3e..9c2ec05aac 100644 --- a/src/components/homesections/homesections.js +++ b/src/components/homesections/homesections.js @@ -1,4 +1,4 @@ -define(['connectionManager', 'cardBuilder', 'registrationServices', 'appSettings', 'dom', 'apphost', 'layoutManager', 'imageLoader', 'globalize', 'itemShortcuts', 'itemHelper', 'appRouter', 'emby-button', 'paper-icon-button-light', 'emby-itemscontainer', 'emby-scroller', 'emby-linkbutton', 'css!./homesections'], function (connectionManager, cardBuilder, registrationServices, appSettings, dom, appHost, layoutManager, imageLoader, globalize, itemShortcuts, itemHelper, appRouter) { +define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'layoutManager', 'imageLoader', 'globalize', 'itemShortcuts', 'itemHelper', 'appRouter', 'emby-button', 'paper-icon-button-light', 'emby-itemscontainer', 'emby-scroller', 'emby-linkbutton', 'css!./homesections'], function (connectionManager, cardBuilder, appSettings, dom, appHost, layoutManager, imageLoader, globalize, itemShortcuts, itemHelper, appRouter) { 'use strict'; function getDefaultSection(index) { @@ -662,34 +662,10 @@ define(['connectionManager', 'cardBuilder', 'registrationServices', 'appSettings itemsContainer.parentContainer = elem; } - function bindUnlockClick(elem) { - - var btnUnlock = elem.querySelector('.btnUnlock'); - if (btnUnlock) { - btnUnlock.addEventListener('click', function (e) { - - registrationServices.validateFeature('livetv', { - - viewOnly: true - - }).then(function () { - - dom.parentWithClass(elem, 'homeSectionsContainer').dispatchEvent(new CustomEvent('settingschange', { - cancelable: false - })); - }); - }); - } - } - function getOnNowFetchFn(serverId) { - return function () { - var apiClient = connectionManager.getApiClient(serverId); - return apiClient.getLiveTvRecommendedPrograms({ - userId: apiClient.getCurrentUserId(), IsAiring: true, limit: 24, @@ -697,15 +673,12 @@ define(['connectionManager', 'cardBuilder', 'registrationServices', 'appSettings EnableImageTypes: "Primary,Thumb,Backdrop", EnableTotalRecordCount: false, Fields: "ChannelInfo,PrimaryImageAspectRatio" - }); }; } function getOnNowItemsHtml(items) { - var cardLayout = false; - return cardBuilder.getCardsHtml({ items: items, preferThumb: 'auto', @@ -728,27 +701,12 @@ define(['connectionManager', 'cardBuilder', 'registrationServices', 'appSettings } function loadOnNow(elem, apiClient, user) { - if (!user.Policy.EnableLiveTvAccess) { return Promise.resolve(); } - var promises = []; - - promises.push(registrationServices.validateFeature('livetv', - { - viewOnly: true, - showDialog: false - }).then(function () { - return true; - }, function () { - return false; - })); - var userId = user.Id; - - promises.push(apiClient.getLiveTvRecommendedPrograms({ - + apiClient.getLiveTvRecommendedPrograms({ userId: apiClient.getCurrentUserId(), IsAiring: true, limit: 1, @@ -756,17 +714,9 @@ define(['connectionManager', 'cardBuilder', 'registrationServices', 'appSettings EnableImageTypes: "Primary,Thumb,Backdrop", EnableTotalRecordCount: false, Fields: "ChannelInfo,PrimaryImageAspectRatio" - - })); - - return Promise.all(promises).then(function (responses) { - - var registered = responses[0]; - var result = responses[1]; + }).then(function (result) { var html = ''; - - if (result.Items.length && registered) { - + if (result.Items.length) { elem.classList.remove('padded-left'); elem.classList.remove('padded-right'); elem.classList.remove('padded-bottom'); @@ -774,51 +724,38 @@ define(['connectionManager', 'cardBuilder', 'registrationServices', 'appSettings html += '
'; html += '
'; - html += '

' + globalize.translate('LiveTV') + '

'; - html += '
'; if (enableScrollX()) { html += '
'; html += '
'; - } - else { + } else { html += ''; - if (enableScrollX()) { html += '
'; } - html += '
'; html += '
'; @@ -826,12 +763,9 @@ define(['connectionManager', 'cardBuilder', 'registrationServices', 'appSettings html += '
'; if (!layoutManager.tv) { - html += ''; html += '

'; html += globalize.translate('HeaderOnNow'); @@ -863,22 +797,7 @@ define(['connectionManager', 'cardBuilder', 'registrationServices', 'appSettings itemsContainer.parentContainer = elem; itemsContainer.fetchData = getOnNowFetchFn(apiClient.serverId()); itemsContainer.getItemsHtml = getOnNowItemsHtml; - - } else if (result.Items.length && !registered) { - - elem.classList.add('padded-left'); - elem.classList.add('padded-right'); - elem.classList.add('padded-bottom'); - - html += '

' + globalize.translate('LiveTvRequiresUnlock') + '

'; - html += ''; - - elem.innerHTML = html; } - - bindUnlockClick(elem); }); } diff --git a/src/components/playback/playaccessvalidation.js b/src/components/playback/playaccessvalidation.js index bb0b8db3e0..35d8314fc1 100644 --- a/src/components/playback/playaccessvalidation.js +++ b/src/components/playback/playaccessvalidation.js @@ -2,16 +2,13 @@ define(['connectionManager', 'globalize'], function (connectionManager, globaliz "use strict"; function getRequirePromise(deps) { - return new Promise(function (resolve, reject) { - require(deps, resolve); }); } function showErrorMessage() { return getRequirePromise(['alert']).then(function (alert) { - return alert(globalize.translate('MessagePlayAccessRestricted')).then(function () { return Promise.reject(); }); @@ -19,7 +16,6 @@ define(['connectionManager', 'globalize'], function (connectionManager, globaliz } function PlayAccessValidation() { - this.name = 'Playback validation'; this.type = 'preplayintercept'; this.id = 'playaccessvalidation'; @@ -27,7 +23,6 @@ define(['connectionManager', 'globalize'], function (connectionManager, globaliz } PlayAccessValidation.prototype.intercept = function (options) { - var item = options.item; if (!item) { return Promise.resolve(); @@ -38,7 +33,6 @@ define(['connectionManager', 'globalize'], function (connectionManager, globaliz } return connectionManager.getApiClient(serverId).getCurrentUser().then(function (user) { - if (user.Policy.EnableMediaPlayback) { return Promise.resolve(); } diff --git a/src/components/playback/playbackvalidation.js b/src/components/playback/playbackvalidation.js deleted file mode 100644 index c36d5c1b5a..0000000000 --- a/src/components/playback/playbackvalidation.js +++ /dev/null @@ -1,80 +0,0 @@ -define(['playbackManager', 'itemHelper'], function (playbackManager, itemHelper) { - "use strict"; - - function getRequirePromise(deps) { - - return new Promise(function (resolve, reject) { - - require(deps, resolve); - }); - } - - function validatePlayback(options) { - - var feature = 'playback'; - if (options.item && (options.item.Type === 'TvChannel' || options.item.Type === 'Recording')) { - feature = 'livetv'; - } - - if (feature === 'playback') { - var player = playbackManager.getCurrentPlayer(); - if (player && !player.isLocalPlayer) { - return Promise.resolve(); - } - } - - return getRequirePromise(["registrationServices"]).then(function (registrationServices) { - - return registrationServices.validateFeature(feature, options).then(function (result) { - - if (result && result.enableTimeLimit) { - startAutoStopTimer(); - } - }); - }); - } - - var autoStopTimeout; - function startAutoStopTimer() { - stopAutoStopTimer(); - autoStopTimeout = setTimeout(onAutoStopTimeout, 63000); - } - - function onAutoStopTimeout() { - stopAutoStopTimer(); - playbackManager.stop(); - } - - function stopAutoStopTimer() { - - var timeout = autoStopTimeout; - if (timeout) { - clearTimeout(timeout); - autoStopTimeout = null; - } - } - - function PlaybackValidation() { - - this.name = 'Playback validation'; - this.type = 'preplayintercept'; - this.id = 'playbackvalidation'; - this.order = -1; - } - - PlaybackValidation.prototype.intercept = function (options) { - - // Don't care about video backdrops, or theme music or any kind of non-fullscreen playback - if (!options.fullscreen) { - return Promise.resolve(); - } - - if (options.item && itemHelper.isLocalItem(options.item)) { - return Promise.resolve(); - } - - return validatePlayback(options); - }; - - return PlaybackValidation; -}); \ No newline at end of file diff --git a/src/components/recordingcreator/recordingbutton.js b/src/components/recordingcreator/recordingbutton.js index ef4645e6bb..0a76d3914c 100644 --- a/src/components/recordingcreator/recordingbutton.js +++ b/src/components/recordingcreator/recordingbutton.js @@ -1,4 +1,4 @@ -define(['globalize', 'connectionManager', 'require', 'loading', 'apphost', 'dom', 'recordingHelper', 'events', 'registrationServices', 'paper-icon-button-light', 'emby-button', 'css!./recordingfields'], function (globalize, connectionManager, require, loading, appHost, dom, recordingHelper, events, registrationServices) { +define(['globalize', 'connectionManager', 'require', 'loading', 'apphost', 'dom', 'recordingHelper', 'events', 'paper-icon-button-light', 'emby-button', 'css!./recordingfields'], function (globalize, connectionManager, require, loading, appHost, dom, recordingHelper, events) { 'use strict'; function onRecordingButtonClick(e) { diff --git a/src/components/recordingcreator/recordingfields.js b/src/components/recordingcreator/recordingfields.js index ac21784eb9..cb0229d873 100644 --- a/src/components/recordingcreator/recordingfields.js +++ b/src/components/recordingcreator/recordingfields.js @@ -1,75 +1,16 @@ -define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loading', 'apphost', 'dom', 'recordingHelper', 'events', 'registrationServices', 'paper-icon-button-light', 'emby-button', 'css!./recordingfields', 'flexStyles'], function (globalize, connectionManager, serverNotifications, require, loading, appHost, dom, recordingHelper, events, registrationServices) { +define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loading', 'apphost', 'dom', 'recordingHelper', 'events', 'paper-icon-button-light', 'emby-button', 'css!./recordingfields', 'flexStyles'], function (globalize, connectionManager, serverNotifications, require, loading, appHost, dom, recordingHelper, events) { 'use strict'; - function getRegistration(apiClient, feature) { - - return registrationServices.validateFeature(feature, { - showDialog: false, - viewOnly: true - }); - } - - function showConvertRecordingsUnlockMessage(context, apiClient) { - - getRegistration(apiClient, getDvrFeatureCode()).then(function () { - - context.querySelector('.convertRecordingsContainer').classList.add('hide'); - }, function () { - context.querySelector('.convertRecordingsContainer').classList.remove('hide'); - }); - } - function showSeriesRecordingFields(context, programId, apiClient) { - - getRegistration(apiClient, getDvrFeatureCode()).then(function () { - - context.querySelector('.supporterContainer').classList.add('hide'); - context.querySelector('.convertRecordingsContainer').classList.add('hide'); - context.querySelector('.recordSeriesContainer').classList.remove('hide'); - - }, function () { - - context.querySelector('.supporterContainerText').innerHTML = globalize.translate('MessageActiveSubscriptionRequiredSeriesRecordings'); - context.querySelector('.supporterContainer').classList.remove('hide'); - context.querySelector('.recordSeriesContainer').classList.add('hide'); - context.querySelector('.convertRecordingsContainer').classList.add('hide'); - }); - } - - function getDvrFeatureCode() { - - return 'dvr'; + context.querySelector('.convertRecordingsContainer').classList.add('hide'); + context.querySelector('.recordSeriesContainer').classList.remove('hide'); } function showSingleRecordingFields(context, programId, apiClient) { - - getRegistration(apiClient, getDvrFeatureCode()).then(function () { - - context.querySelector('.supporterContainer').classList.add('hide'); - showConvertRecordingsUnlockMessage(context, apiClient); - - }, function () { - - context.querySelector('.supporterContainerText').innerHTML = globalize.translate('DvrSubscriptionRequired'); - context.querySelector('.supporterContainer').classList.remove('hide'); - context.querySelector('.convertRecordingsContainer').classList.add('hide'); - }); - } - - function showRecordingFieldsContainer(context, programId, apiClient) { - - getRegistration(apiClient, getDvrFeatureCode()).then(function () { - - context.querySelector('.recordingFields').classList.remove('hide'); - - }, function () { - - context.querySelector('.recordingFields').classList.add('hide'); - }); + context.querySelector('.convertRecordingsContainer').classList.add('hide'); } function loadData(parent, program, apiClient) { - if (program.IsSeries) { parent.querySelector('.recordSeriesContainer').classList.remove('hide'); showSeriesRecordingFields(parent, program.Id, apiClient); @@ -91,13 +32,11 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa if (program.TimerId && program.Status !== 'Cancelled') { parent.querySelector('.btnManageRecording').classList.remove('hide'); parent.querySelector('.singleRecordingButton .recordingIcon').classList.add('recordingIcon-active'); - if (program.Status === 'InProgress') { parent.querySelector('.singleRecordingButton .buttonText').innerHTML = globalize.translate('StopRecording'); } else { parent.querySelector('.singleRecordingButton .buttonText').innerHTML = globalize.translate('DoNotRecord'); } - } else { parent.querySelector('.btnManageRecording').classList.add('hide'); parent.querySelector('.singleRecordingButton .recordingIcon').classList.remove('recordingIcon-active'); @@ -110,20 +49,16 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa var options = instance.options; var apiClient = connectionManager.getApiClient(options.serverId); - showRecordingFieldsContainer(options.parent, options.programId, apiClient); - + instance.querySelector('.recordingFields').classList.remove('hide'); return apiClient.getLiveTvProgram(options.programId, apiClient.getCurrentUserId()).then(function (program) { - instance.TimerId = program.TimerId; instance.Status = program.Status; instance.SeriesTimerId = program.SeriesTimerId; - loadData(options.parent, program, apiClient); }); } function onTimerChangedExternally(e, apiClient, data) { - var options = this.options; var refresh = false; @@ -144,7 +79,6 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa } function onSeriesTimerChangedExternally(e, apiClient, data) { - var options = this.options; var refresh = false; @@ -181,26 +115,16 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa events.on(serverNotifications, 'SeriesTimerCancelled', seriesTimerChangedHandler); } - function onSupporterButtonClick() { - registrationServices.showPremiereInfo(); - } - function onManageRecordingClick(e) { - var options = this.options; - if (!this.TimerId || this.Status === 'Cancelled') { return; } var self = this; - require(['recordingEditor'], function (recordingEditor) { - recordingEditor.show(self.TimerId, options.serverId, { - enableCancel: false - }).then(function () { self.changed = true; }); @@ -282,21 +206,16 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa if (isChecked) { showSeriesRecordingFields(options.parent, options.programId, apiClient); - if (!this.SeriesTimerId) { - var promise = this.TimerId ? recordingHelper.changeRecordingToSeries(apiClient, this.TimerId, options.programId) : recordingHelper.createRecording(apiClient, options.programId, true); - promise.then(function () { fetchData(self); }); } } else { - showSingleRecordingFields(options.parent, options.programId, apiClient); - if (this.SeriesTimerId) { apiClient.cancelLiveTvSeriesTimer(this.SeriesTimerId).then(function () { sendToast(globalize.translate('RecordingCancelled')); @@ -307,22 +226,13 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa } RecordingEditor.prototype.embed = function () { - var self = this; - return new Promise(function (resolve, reject) { - require(['text!./recordingfields.template.html'], function (template) { - var options = self.options; var context = options.parent; context.innerHTML = globalize.translateDocument(template, 'core'); - var supporterButtons = context.querySelectorAll('.btnSupporter'); - for (var i = 0, length = supporterButtons.length; i < length; i++) { - supporterButtons[i].addEventListener('click', onSupporterButtonClick); - } - context.querySelector('.singleRecordingButton').addEventListener('click', onRecordChange.bind(self)); context.querySelector('.seriesRecordingButton').addEventListener('click', onRecordSeriesChange.bind(self)); context.querySelector('.btnManageRecording').addEventListener('click', onManageRecordingClick.bind(self)); @@ -334,17 +244,14 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa }; RecordingEditor.prototype.hasChanged = function () { - return this.changed; }; RecordingEditor.prototype.refresh = function () { - fetchData(this); }; RecordingEditor.prototype.destroy = function () { - var timerChangedHandler = this.timerChangedHandler; this.timerChangedHandler = null; diff --git a/src/components/recordingcreator/recordingfields.template.html b/src/components/recordingcreator/recordingfields.template.html index 4e4fb4878b..895e533400 100644 --- a/src/components/recordingcreator/recordingfields.template.html +++ b/src/components/recordingcreator/recordingfields.template.html @@ -1,20 +1,8 @@

${HeaderConvertYourRecordings}

${PromoConvertRecordingsToStreamingFormat}
-
- -
-
-
-
-
-
", html += '
', html += '
' + user.Name + "
", html += "
", html += "
", html += "" } diff --git a/src/controllers/myprofile.js b/src/controllers/myprofile.js index 45f099593d..71baf40a41 100644 --- a/src/controllers/myprofile.js +++ b/src/controllers/myprofile.js @@ -10,7 +10,7 @@ define(["controllers/userpasswordpage", "loading", "libraryMenu", "apphost", "em uploadUserImage.value = ""; uploadUserImage.dispatchEvent(new CustomEvent("change", {})); libraryMenu.setTitle(user.Name); - var imageUrl = "css/images/logindefault.png"; + var imageUrl = "img/logindefault.png"; if (user.PrimaryImageTag) { imageUrl = ApiClient.getUserImageUrl(user.Id, { height: 200, diff --git a/src/devices/ios/ios.css b/src/css/ios.css similarity index 100% rename from src/devices/ios/ios.css rename to src/css/ios.css diff --git a/src/css/nowplaying.css b/src/css/nowplaying.css index ab8695deed..9bedb33c83 100644 --- a/src/css/nowplaying.css +++ b/src/css/nowplaying.css @@ -178,7 +178,7 @@ .playlistIndexIndicatorImage { -webkit-background-size: initial initial !important; background-size: initial !important; - background-image: url(images/ani_equalizer_white.gif) !important + background-image: url(../img/equalizer.gif) !important } .hideVideoButtons .videoButton { diff --git a/src/css/images/ani_equalizer_white.gif b/src/img/equalizer.gif similarity index 100% rename from src/css/images/ani_equalizer_white.gif rename to src/img/equalizer.gif diff --git a/src/css/images/logindefault.png b/src/img/logindefault.png similarity index 100% rename from src/css/images/logindefault.png rename to src/img/logindefault.png diff --git a/src/css/images/logoblack.png b/src/img/logoblack.png similarity index 100% rename from src/css/images/logoblack.png rename to src/img/logoblack.png diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index fb4d100971..56339b7075 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -440,7 +440,7 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " return getToolsMenuHtml(apiClient).then(function (toolsMenuHtml) { var html = ""; html += '
"; html += toolsMenuHtml; navDrawerScrollContainer.innerHTML = html; diff --git a/src/scripts/site.js b/src/scripts/site.js index 280ee85a1e..8f809cfdc1 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -600,7 +600,7 @@ var AppInfo = {}; } else { if (browser.iOS) { - require(['css!devices/ios/ios.css']); + require(['css!css/ios.css']); } window.Emby.Page = appRouter; From c1649d6e653ea6255160db5cf4abeb9ce10d29ef Mon Sep 17 00:00:00 2001 From: dkanada Date: Fri, 22 Mar 2019 03:21:26 -0700 Subject: [PATCH 149/220] fix theme videos option always enabled --- src/scripts/site.js | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 8f809cfdc1..dae98519c9 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -316,20 +316,6 @@ var AppInfo = {}; } function getSettingsBuilder(UserSettings, layoutManager, browser) { - UserSettings.prototype.enableThemeVideos = function (val) { - if (val != null) { - return this.set('enableThemeVideos', val.toString(), false); - } - - val = this.get('enableThemeVideos', false); - - if (val !== 'false') { - return !layoutManager.mobile; - } else { - return !browser.slow; - } - }; - return UserSettings; } From 4df59cc345cd07f176f95b4f9e5018a884c6324b Mon Sep 17 00:00:00 2001 From: dkanada Date: Fri, 22 Mar 2019 11:56:15 -0700 Subject: [PATCH 150/220] move thirdparty libs and assets out of components folder --- src/{components/fonts => css}/fonts.css | 0 src/{components/fonts => css}/fonts.sized.css | 0 .../flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff | Bin .../flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2 | Bin .../fonts => css}/material-icons/style.css | 0 src/scripts/site.js | 16 ++++++++-------- src/{components => thirdparty}/flvjs/flv.min.js | 0 .../native-promise-only/lib/npo.src.js | 0 .../native-promise-only/test_adapter.js | 0 src/{components => thirdparty}/pagejs/page.js | 0 .../resize-observer-polyfill/ResizeObserver.js | 0 11 files changed, 8 insertions(+), 8 deletions(-) rename src/{components/fonts => css}/fonts.css (100%) rename src/{components/fonts => css}/fonts.sized.css (100%) rename src/{components/fonts => css}/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff (100%) rename src/{components/fonts => css}/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2 (100%) rename src/{components/fonts => css}/material-icons/style.css (100%) rename src/{components => thirdparty}/flvjs/flv.min.js (100%) rename src/{components => thirdparty}/native-promise-only/lib/npo.src.js (100%) rename src/{components => thirdparty}/native-promise-only/test_adapter.js (100%) rename src/{components => thirdparty}/pagejs/page.js (100%) rename src/{components => thirdparty}/resize-observer-polyfill/ResizeObserver.js (100%) diff --git a/src/components/fonts/fonts.css b/src/css/fonts.css similarity index 100% rename from src/components/fonts/fonts.css rename to src/css/fonts.css diff --git a/src/components/fonts/fonts.sized.css b/src/css/fonts.sized.css similarity index 100% rename from src/components/fonts/fonts.sized.css rename to src/css/fonts.sized.css diff --git a/src/components/fonts/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff b/src/css/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff similarity index 100% rename from src/components/fonts/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff rename to src/css/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff diff --git a/src/components/fonts/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2 b/src/css/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2 similarity index 100% rename from src/components/fonts/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2 rename to src/css/material-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2 diff --git a/src/components/fonts/material-icons/style.css b/src/css/material-icons/style.css similarity index 100% rename from src/components/fonts/material-icons/style.css rename to src/css/material-icons/style.css diff --git a/src/scripts/site.js b/src/scripts/site.js index dae98519c9..6eb45b86d9 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -396,7 +396,7 @@ var AppInfo = {}; return self.ResizeObserver; }); } else { - define("ResizeObserver", ["components/resize-observer-polyfill/ResizeObserver"], returnFirstDependency); + define("ResizeObserver", ["thirdparty/resize-observer-polyfill/ResizeObserver"], returnFirstDependency); } } @@ -672,7 +672,7 @@ var AppInfo = {}; } if (!window.Promise || browser.web0s) { - require(["components/native-promise-only/lib/npo.src"], init); + require(["thirdparty/native-promise-only/lib/npo.src"], init); } else { init(); } @@ -710,7 +710,7 @@ var AppInfo = {}; inputManager: componentsPath + "/inputmanager", qualityoptions: componentsPath + "/qualityoptions", hammer: bowerPath + "/hammerjs/hammer.min", - pageJs: componentsPath + "/pagejs/page", + pageJs: "thirdparty/pagejs/page", focusManager: componentsPath + "/focusmanager", datetime: componentsPath + "/datetime", globalize: componentsPath + "/globalize", @@ -723,8 +723,8 @@ var AppInfo = {}; packageManager: componentsPath + "/packagemanager" }; paths.hlsjs = bowerPath + "/hlsjs/dist/hls.min"; - paths.flvjs = componentsPath + "/flvjs/flv.min"; - paths.shaka = componentsPath + "/shaka/shaka-player.compiled"; + paths.flvjs = "thirdparty/flvjs/flv.min"; + paths.shaka = "thirdparty/shaka/shaka-player.compiled"; define("chromecastHelper", [componentsPath + "/chromecast/chromecasthelpers"], returnFirstDependency); define("mediaSession", [componentsPath + "/playback/mediasession"], returnFirstDependency); define("actionsheet", [componentsPath + "/actionsheet/actionsheet"], returnFirstDependency); @@ -863,9 +863,9 @@ var AppInfo = {}; define("appSettings", [componentsPath + "/appsettings"], returnFirstDependency); define("userSettings", [componentsPath + "/usersettings/usersettings"], returnFirstDependency); define("userSettingsBuilder", [componentsPath + "/usersettings/usersettingsbuilder", "layoutManager", "browser"], getSettingsBuilder); - define("material-icons", ["css!" + componentsPath + "/fonts/material-icons/style"], returnFirstDependency); - define("systemFontsCss", ["css!" + componentsPath + "/fonts/fonts"], returnFirstDependency); - define("systemFontsSizedCss", ["css!" + componentsPath + "/fonts/fonts.sized"], returnFirstDependency); + define("material-icons", ["css!css/material-icons/style"], returnFirstDependency); + define("systemFontsCss", ["css!css/fonts"], returnFirstDependency); + define("systemFontsSizedCss", ["css!css/fonts.sized"], returnFirstDependency); define("scrollStyles", ["css!" + componentsPath + "/scrollstyles"], returnFirstDependency); define("imageUploader", [componentsPath + "/imageuploader/imageuploader"], returnFirstDependency); define("navdrawer", ["components/navdrawer/navdrawer"], returnFirstDependency); diff --git a/src/components/flvjs/flv.min.js b/src/thirdparty/flvjs/flv.min.js similarity index 100% rename from src/components/flvjs/flv.min.js rename to src/thirdparty/flvjs/flv.min.js diff --git a/src/components/native-promise-only/lib/npo.src.js b/src/thirdparty/native-promise-only/lib/npo.src.js similarity index 100% rename from src/components/native-promise-only/lib/npo.src.js rename to src/thirdparty/native-promise-only/lib/npo.src.js diff --git a/src/components/native-promise-only/test_adapter.js b/src/thirdparty/native-promise-only/test_adapter.js similarity index 100% rename from src/components/native-promise-only/test_adapter.js rename to src/thirdparty/native-promise-only/test_adapter.js diff --git a/src/components/pagejs/page.js b/src/thirdparty/pagejs/page.js similarity index 100% rename from src/components/pagejs/page.js rename to src/thirdparty/pagejs/page.js diff --git a/src/components/resize-observer-polyfill/ResizeObserver.js b/src/thirdparty/resize-observer-polyfill/ResizeObserver.js similarity index 100% rename from src/components/resize-observer-polyfill/ResizeObserver.js rename to src/thirdparty/resize-observer-polyfill/ResizeObserver.js From ed812281bc505a58ee4270b6577528df21dc19fa Mon Sep 17 00:00:00 2001 From: dkanada Date: Fri, 22 Mar 2019 12:14:41 -0700 Subject: [PATCH 151/220] update some old string references --- .../serverrestartdialog.js | 2 +- src/controllers/dashboardpage.js | 6 ---- src/controllers/wizarduserpage.js | 34 ++++++++----------- src/dashboard.html | 16 ++------- src/strings/en-us.json | 2 ++ 5 files changed, 20 insertions(+), 40 deletions(-) diff --git a/src/components/serverrestartdialog/serverrestartdialog.js b/src/components/serverrestartdialog/serverrestartdialog.js index 6e284b6125..c2469afc9d 100644 --- a/src/components/serverrestartdialog/serverrestartdialog.js +++ b/src/components/serverrestartdialog/serverrestartdialog.js @@ -94,7 +94,7 @@ define(['loading', 'events', 'dialogHelper', 'dom', 'layoutManager', 'scrollHelp // dialogHelper.close(dlg); //}); - dlg.querySelector('.formDialogHeaderTitle').innerHTML = globalize.translate('HeaderRestartingEmbyServer'); + dlg.querySelector('.formDialogHeaderTitle').innerHTML = globalize.translate('RestartingServer'); dlg.querySelector('.text').innerHTML = globalize.translate('RestartPleaseWaitMessage'); diff --git a/src/controllers/dashboardpage.js b/src/controllers/dashboardpage.js index 0dc1f4e6fa..2a70208131 100644 --- a/src/controllers/dashboardpage.js +++ b/src/controllers/dashboardpage.js @@ -1,11 +1,6 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globalize", "loading", "connectionManager", "playMethodHelper", "cardBuilder", "imageLoader", "components/activitylog", "humanedate", "listViewStyle", "emby-linkbutton", "flexStyles", "emby-button", "emby-itemscontainer"], function (datetime, events, itemHelper, serverNotifications, dom, globalize, loading, connectionManager, playMethodHelper, cardBuilder, imageLoader, ActivityLog) { "use strict"; - function onConnectionHelpClick(evt) { - evt.preventDefault(); - return false; - } - function buttonEnabled(elem, enabled) { if (enabled) { elem.setAttribute("disabled", ""); @@ -847,7 +842,6 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa } var serverId = ApiClient.serverId(); - view.querySelector(".btnConnectionHelp").addEventListener("click", onConnectionHelpClick); view.querySelector(".btnEditServerName").addEventListener("click", onEditServerNameClick); view.querySelector(".activeDevices").addEventListener("click", onActiveDevicesClick); view.addEventListener("viewshow", function () { diff --git a/src/controllers/wizarduserpage.js b/src/controllers/wizarduserpage.js index 252e005a80..c3508efc12 100644 --- a/src/controllers/wizarduserpage.js +++ b/src/controllers/wizarduserpage.js @@ -2,22 +2,17 @@ define(["loading", "globalize", "dashboardcss", "emby-input", "emby-button", "em "use strict"; function getApiClient() { - return ApiClient + return ApiClient; } function nextWizardPage() { - Dashboard.navigate("wizardlibrary.html") + Dashboard.navigate("wizardlibrary.html"); } function onUpdateUserComplete(result) { - if (loading.hide(), result.UserLinkResult) { - var msgKey = result.UserLinkResult.IsPending ? "MessagePendingEmbyAccountAdded" : "MessageEmbyAccountAdded"; - Dashboard.alert({ - message: globalize.translate(msgKey), - title: globalize.translate("HeaderEmbyAccountAdded"), - callback: nextWizardPage - }) - } else nextWizardPage() + console.log(result); + loading.hide(); + nextWizardPage(); } function submit(form) { @@ -27,12 +22,10 @@ define(["loading", "globalize", "dashboardcss", "emby-input", "emby-button", "em type: "POST", data: { Name: form.querySelector("#txtUsername").value, - Password: form.querySelector("#txtManualPassword").value + Password: form.querySelector("#txtManualPassword").value }, url: apiClient.getUrl("Startup/User") - }).then(onUpdateUserComplete, function(response) { - console.log(response); - }) + }).then(onUpdateUserComplete); } function onSubmit(e) { @@ -50,8 +43,8 @@ define(["loading", "globalize", "dashboardcss", "emby-input", "emby-button", "em function onViewShow() { loading.show(); - var page = this, - apiClient = getApiClient(); + var page = this; + var apiClient = getApiClient(); apiClient.getJSON(apiClient.getUrl("Startup/User")).then(function(user) { page.querySelector("#txtUsername").value = user.Name || ""; page.querySelector("#txtManualPassword").value = user.Password || ""; @@ -59,10 +52,13 @@ define(["loading", "globalize", "dashboardcss", "emby-input", "emby-button", "em }) } return function(view, params) { - view.querySelector(".wizardUserForm").addEventListener("submit", onSubmit), view.addEventListener("viewshow", function() { + view.querySelector(".wizardUserForm").addEventListener("submit", onSubmit); + view.addEventListener("viewshow", function() { document.querySelector(".skinHeader").classList.add("noHomeButtonHeader") - }), view.addEventListener("viewhide", function() { + }); + view.addEventListener("viewhide", function() { document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader") - }), view.addEventListener("viewshow", onViewShow) + }); + view.addEventListener("viewshow", onViewShow); } }); diff --git a/src/dashboard.html b/src/dashboard.html index 6c751740c3..25f4278beb 100644 --- a/src/dashboard.html +++ b/src/dashboard.html @@ -1,30 +1,20 @@
-
-
-
-

-
+
-

-

+

-

-

-

- ${HowToConnectFromEmbyApps} -

@@ -36,13 +26,11 @@
-

${HeaderRunningTasks}

-
diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 5947fa6370..6bb916e375 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -442,6 +442,7 @@ "HeaderResponseProfile": "Response Profile", "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.", "HeaderRestart": "Restart", + "HeaderRestartingServer": "Restarting Server", "HeaderRevisionHistory": "Revision History", "HeaderRunningTasks": "Running Tasks", "HeaderScenes": "Scenes", @@ -955,6 +956,7 @@ "MessageItemsAdded": "Items added.", "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.", "MessageNoAvailablePlugins": "No available plugins.", + "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, and albums Albums. Click the + button to start creating collections.", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoPluginsInstalled": "You have no plugins installed.", "MessageNoServersAvailableToConnect": "No servers are available to connect to. If you've been invited to share a server, make sure to accept it below or by clicking the link in the email.", From 3b576be5f01d06cfc7c83bccdc80631aad386019 Mon Sep 17 00:00:00 2001 From: dkanada Date: Fri, 22 Mar 2019 13:25:00 -0700 Subject: [PATCH 152/220] move some links to the new documentation --- src/addplugin.html | 2 +- src/components/apiInput/apiInput.js | 11 ++--------- src/components/apphost.js | 2 -- src/components/playback/playbackmanager.js | 16 +++++----------- .../serverrestartdialog/serverrestartdialog.js | 7 ------- src/dashboard/aboutpage.js | 9 --------- src/plugincatalog.html | 2 +- 7 files changed, 9 insertions(+), 40 deletions(-) delete mode 100644 src/dashboard/aboutpage.js diff --git a/src/addplugin.html b/src/addplugin.html index efdfbcc3d3..08c36fb194 100644 --- a/src/addplugin.html +++ b/src/addplugin.html @@ -8,7 +8,7 @@

diff --git a/src/components/apiInput/apiInput.js b/src/components/apiInput/apiInput.js index c12f933553..388fb11beb 100644 --- a/src/components/apiInput/apiInput.js +++ b/src/components/apiInput/apiInput.js @@ -27,28 +27,21 @@ define(['connectionManager', 'playbackManager', 'events', 'inputManager', 'focus } function displayContent(cmd, apiClient) { - if (!playbackManager.isPlayingLocally(['Video', 'Book'])) { appRouter.showItem(cmd.Arguments.ItemId, apiClient.serverId()); } } function playTrailers(apiClient, itemId) { - apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) { - playbackManager.playTrailers(item); }); } function processGeneralCommand(cmd, apiClient) { - - // Full list - // https://github.com/MediaBrowser/MediaBrowser/blob/master/MediaBrowser.Model/Session/GeneralCommand.cs#L23 - //console.log('Received command: ' + cmd.Name); - + // https://github.com/jellyfin/jellyfin/blob/master/MediaBrowser.Model/Session/GeneralCommandType.cs + console.log('Received command: ' + cmd.Name); switch (cmd.Name) { - case 'Select': inputManager.trigger('select'); return; diff --git a/src/components/apphost.js b/src/components/apphost.js index 369dff0f6f..4106cac285 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -390,8 +390,6 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet } }, deviceIconUrl: function () { - browser.edgeUwp; - if (browser.edgeUwp) { return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/windowsrt.png"; } diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index b0904c4e96..33b0b2b793 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -3805,8 +3805,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla player = player || this._currentPlayer || { isLocalPlayer: true }; if (player.isLocalPlayer) { - // Full list - // https://github.com/MediaBrowser/MediaBrowser/blob/master/MediaBrowser.Model/Session/GeneralCommand.cs + // https://github.com/jellyfin/jellyfin/blob/master/MediaBrowser.Model/Session/GeneralCommandType.cs var list = [ "GoHome", "GoToSettings", @@ -3934,12 +3933,9 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla }; PlaybackManager.prototype.sendCommand = function (cmd, player) { - - // Full list - // https://github.com/MediaBrowser/MediaBrowser/blob/master/MediaBrowser.Model/Session/GeneralCommand.cs#L23 + // https://github.com/jellyfin/jellyfin/blob/master/MediaBrowser.Model/Session/GeneralCommandType.cs console.log('MediaController received command: ' + cmd.Name); switch (cmd.Name) { - case 'SetRepeatMode': this.setRepeatMode(cmd.Arguments.RepeatMode, player); break; @@ -3981,12 +3977,10 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla this.toggleFullscreen(player); break; default: - { - if (player.sendCommand) { - player.sendCommand(cmd); - } - break; + if (player.sendCommand) { + player.sendCommand(cmd); } + break; } }; diff --git a/src/components/serverrestartdialog/serverrestartdialog.js b/src/components/serverrestartdialog/serverrestartdialog.js index c2469afc9d..02cb1af039 100644 --- a/src/components/serverrestartdialog/serverrestartdialog.js +++ b/src/components/serverrestartdialog/serverrestartdialog.js @@ -90,10 +90,6 @@ define(['loading', 'events', 'dialogHelper', 'dom', 'layoutManager', 'scrollHelp dlg.classList.add('dialog-fullscreen-lowres'); } - //dlg.querySelector('.btnCancel').addEventListener('click', function (e) { - // dialogHelper.close(dlg); - //}); - dlg.querySelector('.formDialogHeaderTitle').innerHTML = globalize.translate('RestartingServer'); dlg.querySelector('.text').innerHTML = globalize.translate('RestartPleaseWaitMessage'); @@ -101,16 +97,13 @@ define(['loading', 'events', 'dialogHelper', 'dom', 'layoutManager', 'scrollHelp var i, length; var html = ''; for (i = 0, length = configuredButtons.length; i < length; i++) { - var item = configuredButtons[i]; var autoFocus = i === 0 ? ' autofocus' : ''; - var buttonClass = 'btnOption raised formDialogFooterItem formDialogFooterItem-autosize'; if (item.type) { buttonClass += ' button-' + item.type; } - html += ''; } diff --git a/src/dashboard/aboutpage.js b/src/dashboard/aboutpage.js deleted file mode 100644 index 7ad9285455..0000000000 --- a/src/dashboard/aboutpage.js +++ /dev/null @@ -1,9 +0,0 @@ -define([], function() { - "use strict"; - return function(view, params) { - view.addEventListener("viewbeforeshow", function(e) { - var elem = view.querySelector("#appVersionNumber"); - elem.innerHTML = elem.innerHTML.replace("{0}", ConnectionManager.appVersion()) - }) - } -}); \ No newline at end of file diff --git a/src/plugincatalog.html b/src/plugincatalog.html index 6bd71a5b28..53579d16a3 100644 --- a/src/plugincatalog.html +++ b/src/plugincatalog.html @@ -12,7 +12,7 @@
- ${Help} + ${Help}
From 9a6f0a12c84346c5c0f2e4bde0ec21147434ce5c Mon Sep 17 00:00:00 2001 From: dkanada Date: Fri, 22 Mar 2019 15:47:01 -0700 Subject: [PATCH 153/220] move server name setting to general page --- .../serverrestartdialog.js | 2 +- src/controllers/dashboardgeneral.js | 2 + src/controllers/dashboardpage.js | 45 ++++--------------- src/dashboard.html | 13 +++--- src/dashboardgeneral.html | 4 ++ src/strings/ar.json | 2 +- src/strings/ca.json | 2 +- src/strings/cs.json | 2 +- src/strings/da.json | 2 +- src/strings/de.json | 2 +- src/strings/el.json | 2 +- src/strings/en-us.json | 5 ++- src/strings/es-mx.json | 2 +- src/strings/es.json | 2 +- src/strings/fr.json | 2 +- src/strings/he.json | 2 +- src/strings/hr.json | 2 +- src/strings/hu.json | 2 +- src/strings/it.json | 2 +- src/strings/kk.json | 2 +- src/strings/ko.json | 2 +- src/strings/lt-lt.json | 2 +- src/strings/nb.json | 2 +- src/strings/nl.json | 2 +- src/strings/pl.json | 2 +- src/strings/pt-br.json | 2 +- src/strings/pt-pt.json | 2 +- src/strings/ru.json | 2 +- src/strings/sk.json | 2 +- src/strings/sv.json | 2 +- src/strings/zh-cn.json | 2 +- src/strings/zh-hk.json | 2 +- src/strings/zh-tw.json | 2 +- 33 files changed, 52 insertions(+), 73 deletions(-) diff --git a/src/components/serverrestartdialog/serverrestartdialog.js b/src/components/serverrestartdialog/serverrestartdialog.js index 02cb1af039..6c7e5b7386 100644 --- a/src/components/serverrestartdialog/serverrestartdialog.js +++ b/src/components/serverrestartdialog/serverrestartdialog.js @@ -90,7 +90,7 @@ define(['loading', 'events', 'dialogHelper', 'dom', 'layoutManager', 'scrollHelp dlg.classList.add('dialog-fullscreen-lowres'); } - dlg.querySelector('.formDialogHeaderTitle').innerHTML = globalize.translate('RestartingServer'); + dlg.querySelector('.formDialogHeaderTitle').innerHTML = globalize.translate('HeaderRestartingServer'); dlg.querySelector('.text').innerHTML = globalize.translate('RestartPleaseWaitMessage'); diff --git a/src/controllers/dashboardgeneral.js b/src/controllers/dashboardgeneral.js index ed3b000b12..6a3f80d3a2 100644 --- a/src/controllers/dashboardgeneral.js +++ b/src/controllers/dashboardgeneral.js @@ -2,6 +2,7 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb "use strict"; function loadPage(page, config, languageOptions, systemInfo) { + page.querySelector("#txtServerName").value = config.ServerName; if (systemInfo.CanLaunchWebBrowser) { page.querySelector("#fldRunWebAppAtStartup").classList.remove("hide"); } else { @@ -39,6 +40,7 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb var form = this; $(form).parents(".page"); return ApiClient.getServerConfiguration().then(function(config) { + config.ServerName = $("#txtServerName", form).val(); config.UICulture = $("#selectLocalizationLanguage", form).val(); config.CachePath = form.querySelector("#txtCachePath").value; config.MetadataPath = $("#txtMetadataPath", form).val(); diff --git a/src/controllers/dashboardpage.js b/src/controllers/dashboardpage.js index 2a70208131..5fb20f953c 100644 --- a/src/controllers/dashboardpage.js +++ b/src/controllers/dashboardpage.js @@ -10,31 +10,6 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa } } - function onEditServerNameClick(evt) { - var page = dom.parentWithClass(this, "page"); - - require(["prompt"], function (prompt) { - prompt({ - label: globalize.translate("LabelFriendlyServerName"), - description: globalize.translate("LabelFriendlyServerNameHelp"), - value: page.querySelector(".serverNameHeader").innerHTML, - confirmText: globalize.translate("ButtonSave") - }).then(function (value) { - loading.show(); - ApiClient.getServerConfiguration().then(function (config) { - config.ServerName = value; - ApiClient.updateServerConfiguration(config).then(function () { - page.querySelector(".serverNameHeader").innerHTML = value; - loading.hide(); - }); - }); - }); - }); - - evt.preventDefault(); - return false; - } - function showPlaybackInfo(btn, session) { require(["alert"], function (alert) { var showTranscodeReasons; @@ -202,20 +177,13 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa function reloadSystemInfo(view, apiClient) { apiClient.getSystemInfo().then(function (systemInfo) { - view.querySelector(".serverNameHeader").innerHTML = systemInfo.ServerName; - var localizedVersion = globalize.translate("LabelVersionNumber", systemInfo.Version); + view.querySelector("#serverName").innerHTML = globalize.translate("LabelServerName", systemInfo.ServerName); + var localizedVersion = globalize.translate("LabelVersionNumber", systemInfo.Version); if (systemInfo.SystemUpdateLevel && "Release" != systemInfo.SystemUpdateLevel) { localizedVersion += " " + globalize.translate("Option" + systemInfo.SystemUpdateLevel).toLowerCase(); } - - if (systemInfo.CanSelfRestart) { - view.querySelector("#btnRestartServer").classList.remove("hide"); - } else { - view.querySelector("#btnRestartServer").classList.add("hide"); - } - - view.querySelector("#appVersionNumber").innerHTML = localizedVersion; + view.querySelector("#versionNumber").innerHTML = localizedVersion; if (systemInfo.SupportsHttps) { view.querySelector("#ports").innerHTML = globalize.translate("LabelRunningOnPorts", systemInfo.HttpServerPortNumber, systemInfo.HttpsPortNumber); @@ -225,6 +193,12 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa DashboardPage.renderUrls(view, systemInfo); DashboardPage.renderPaths(view, systemInfo); + + if (systemInfo.CanSelfRestart) { + view.querySelector("#btnRestartServer").classList.remove("hide"); + } else { + view.querySelector("#btnRestartServer").classList.add("hide"); + } }); } @@ -842,7 +816,6 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa } var serverId = ApiClient.serverId(); - view.querySelector(".btnEditServerName").addEventListener("click", onEditServerNameClick); view.querySelector(".activeDevices").addEventListener("click", onActiveDevicesClick); view.addEventListener("viewshow", function () { var page = this; diff --git a/src/dashboard.html b/src/dashboard.html index 25f4278beb..90ee2580f2 100644 --- a/src/dashboard.html +++ b/src/dashboard.html @@ -3,15 +3,14 @@
-
-

- -
+ +

${TabServer}

+ +
-

+

+

diff --git a/src/dashboardgeneral.html b/src/dashboardgeneral.html index 94eeb23718..f41fc80d46 100644 --- a/src/dashboardgeneral.html +++ b/src/dashboardgeneral.html @@ -13,6 +13,10 @@
+
+ +
${LabelServerNameHelp}
+
diff --git a/src/strings/ar.json b/src/strings/ar.json index d546d06dcf..d5abe0e578 100644 --- a/src/strings/ar.json +++ b/src/strings/ar.json @@ -405,7 +405,7 @@ "LabelFormat": "الصيغة:", "LabelFriendlyName": "اسم مخصوص لك", "LabelFriendlyServerName": "اسم الخادم الميسر:", - "LabelFriendlyServerNameHelp": "هذا الاسم يسيتخدم للتعرف على الخادم. إن ترك خالٍ، فإن اسم الحاسوب سوف يستخدم.", + "LabelServerNameHelp": "هذا الاسم يسيتخدم للتعرف على الخادم. إن ترك خالٍ، فإن اسم الحاسوب سوف يستخدم.", "LabelGroupMoviesIntoCollections": "تجميع الأفلام إلى مجاميع", "LabelGroupMoviesIntoCollectionsHelp": "عند استعراض قوائم الأفلام، فإن الأفلام التي تنتمي إلى مجموعة واحدة ستظهر كعنصر جامع.", "LabelH264Crf": "قيمة CRF لتشفير H264:", diff --git a/src/strings/ca.json b/src/strings/ca.json index 2dcf301198..f175917e81 100644 --- a/src/strings/ca.json +++ b/src/strings/ca.json @@ -339,7 +339,7 @@ "LabelFinish": "Finalitzar", "LabelFriendlyName": "Nom amistós", "LabelFriendlyServerName": "Nom amistós del servidor:", - "LabelFriendlyServerNameHelp": "El nom servirà per identificar aquest servidor. Si es deixa en blanc s'emprarà el nom de l'ordinador.", + "LabelServerNameHelp": "El nom servirà per identificar aquest servidor. Si es deixa en blanc s'emprarà el nom de l'ordinador.", "LabelGroupMoviesIntoCollections": "Agrupa pel·lícules a col·leccions", "LabelHomeScreenSectionValue": "Secció {0} de la pàgina d'inici:", "LabelHttpsPort": "Port local https:", diff --git a/src/strings/cs.json b/src/strings/cs.json index c1e265a7ec..cd5e55fcb9 100644 --- a/src/strings/cs.json +++ b/src/strings/cs.json @@ -541,7 +541,7 @@ "LabelFormat": "Formát:", "LabelFriendlyName": "Přívětivý název", "LabelFriendlyServerName": "Název serveru:", - "LabelFriendlyServerNameHelp": "Toto jméno bude použito jako identifikace serveru, ponecháte-li prázdné bude použit název počítače.", + "LabelServerNameHelp": "Toto jméno bude použito jako identifikace serveru, ponecháte-li prázdné bude použit název počítače.", "LabelGroupMoviesIntoCollections": "Seskupit filmy do kolekcí.", "LabelGroupMoviesIntoCollectionsHelp": "Při zobrazení seznamů filmu, budou filmy patřící do kolekce, zobrazeny jako jedna položka.", "LabelH264Crf": "H264 kódování CRF:", diff --git a/src/strings/da.json b/src/strings/da.json index 47c3c5d094..c3fc4f224e 100644 --- a/src/strings/da.json +++ b/src/strings/da.json @@ -498,7 +498,7 @@ "LabelForgotPasswordUsernameHelp": "Indtast dit brugernavn, hvis du kan huske det.", "LabelFriendlyName": "System venligt navn:", "LabelFriendlyServerName": "Nemt servernavn:", - "LabelFriendlyServerNameHelp": "Dette navn bruges til at identificere serveren. Hvis det ikke udfyldes, bruges computerens navn.", + "LabelServerNameHelp": "Dette navn bruges til at identificere serveren. Hvis det ikke udfyldes, bruges computerens navn.", "LabelGroupMoviesIntoCollections": "Grupper film i samlinger", "LabelGroupMoviesIntoCollectionsHelp": "Film i samlinger vil blive vist som en samlet enhed i filmlister.", "LabelH264Crf": "H264-kodning CRF:", diff --git a/src/strings/de.json b/src/strings/de.json index d1c3f4580a..334c0f507e 100644 --- a/src/strings/de.json +++ b/src/strings/de.json @@ -598,7 +598,7 @@ "LabelForgotPasswordUsernameHelp": "Bitte gib deinen Benutzernamen ein, falls du dich daran erinnerst.", "LabelFriendlyName": "Benutzerfreundlicher Name:", "LabelFriendlyServerName": "Freundlicher Servername:", - "LabelFriendlyServerNameHelp": "Dieser Name wird benutzt um diesen Server zu identifizieren. Wenn leer gelassen, wird der Computername benutzt.", + "LabelServerNameHelp": "Dieser Name wird benutzt um diesen Server zu identifizieren. Wenn leer gelassen, wird der Computername benutzt.", "LabelGroupMoviesIntoCollections": "Gruppiere Filme in Collections", "LabelGroupMoviesIntoCollectionsHelp": "Wenn Filmlisten angezeigt werden, dann werden Filme, die zu einer Collection gehören, als ein gruppiertes Element angezeigt.", "LabelH264EncodingPreset": "H264 Encoding Voreinstellung:", diff --git a/src/strings/el.json b/src/strings/el.json index 86c9a0b57c..064e686d61 100644 --- a/src/strings/el.json +++ b/src/strings/el.json @@ -551,7 +551,7 @@ "LabelFormat": "Φορμάτ:", "LabelFriendlyName": "Φιλικό όνομα", "LabelFriendlyServerName": "Όνομα διακομιστή:", - "LabelFriendlyServerNameHelp": "Αυτό το όνομα θα χρησιμοποιηθεί για την αναγνώριση αυτού του διακομιστή. Αν παραμείνει κενό, θα χρησιμοποιηθεί το όνομα του υπολογιστή.", + "LabelServerNameHelp": "Αυτό το όνομα θα χρησιμοποιηθεί για την αναγνώριση αυτού του διακομιστή. Αν παραμείνει κενό, θα χρησιμοποιηθεί το όνομα του υπολογιστή.", "LabelGroupMoviesIntoCollections": "Ομαδοποιήστε ταινίες σε συλλογές", "LabelGroupMoviesIntoCollectionsHelp": "Όταν προβάλλετε λίστες ταινιών, οι ταινίες που ανήκουν σε μια συλλογή θα εμφανίζονται ως ένα ομαδοποιημένο αντικείμενο.", "LabelHardwareAccelerationType": "Επιτάχυνση υλικού:", diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 6bb916e375..561d1c8e79 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -644,7 +644,7 @@ "LabelFormat": "Format:", "LabelFriendlyName": "Friendly name:", "LabelFriendlyServerName": "Friendly server name:", - "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", + "LabelServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", "LabelGroupMoviesIntoCollections": "Group movies into collections", "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies belonging to a collection will be displayed as one grouped item.", "LabelH264Crf": "H264 encoding CRF:", @@ -802,6 +802,7 @@ "LabelSeriesRecordingPath": "Series recording path (optional):", "LabelServerHost": "Host:", "LabelServerHostHelp": "192.168.1.100 or https://myserver.com", + "LabelServerName": "Server Name: {0}", "LabelServerPort": "Port:", "LabelSimultaneousConnectionLimit": "Simultaneous stream limit:", "LabelSkin": "Skin:", @@ -866,7 +867,7 @@ "LabelValue": "Value:", "LabelVersion": "Version:", "LabelVersionInstalled": "{0} installed", - "LabelVersionNumber": "Version {0}", + "LabelVersionNumber": "Version: {0}", "LabelVideo": "Video:", "LabelWeb": "Web", "LabelXDlnaCap": "X-Dlna cap:", diff --git a/src/strings/es-mx.json b/src/strings/es-mx.json index e2fedfbcc6..f97169e695 100644 --- a/src/strings/es-mx.json +++ b/src/strings/es-mx.json @@ -625,7 +625,7 @@ "LabelFormat": "Formato:", "LabelFriendlyName": "Nombre amistoso:", "LabelFriendlyServerName": "Nombre amigable del servidor:", - "LabelFriendlyServerNameHelp": "Este nombre será usado para identificar este servidor. Si se deja en blanco, se usará el nombre de la computadora.", + "LabelServerNameHelp": "Este nombre será usado para identificar este servidor. Si se deja en blanco, se usará el nombre de la computadora.", "LabelGroupMoviesIntoCollections": "Agrupar películas en colecciones", "LabelGroupMoviesIntoCollectionsHelp": "Cuando se muestran listados de películas, las películas que pertenecen a una colección serán mostradas agrupadas en un solo ítem.", "LabelH264Crf": "CRF de codificación H264:", diff --git a/src/strings/es.json b/src/strings/es.json index 1eb8bd1425..d303394353 100644 --- a/src/strings/es.json +++ b/src/strings/es.json @@ -564,7 +564,7 @@ "LabelFormat": "Formato:", "LabelFriendlyName": "Nombre amigable:", "LabelFriendlyServerName": "Nombre informal del servidor:", - "LabelFriendlyServerNameHelp": "Este nombre se podrá utilizar para identificar este servidor. Si se deja en blanco se usará el nombre del ordenador.", + "LabelServerNameHelp": "Este nombre se podrá utilizar para identificar este servidor. Si se deja en blanco se usará el nombre del ordenador.", "LabelGroupMoviesIntoCollections": "Agrupar películas en colecciones", "LabelGroupMoviesIntoCollectionsHelp": "Cuando se muestran las listas de películas, las películas pertenecientes a una colección se mostrarán como un elemento agrupado.", "LabelH264Crf": "H264 que codifica CRF:", diff --git a/src/strings/fr.json b/src/strings/fr.json index 288486f9b7..8cbd6f1f10 100644 --- a/src/strings/fr.json +++ b/src/strings/fr.json @@ -623,7 +623,7 @@ "LabelFormat": "Format :", "LabelFriendlyName": "Nom d'affichage :", "LabelFriendlyServerName": "Surnom du serveur :", - "LabelFriendlyServerNameHelp": "Ce nom sera utilisé pour identifier le serveur. Sinon le nom d'ordinateur sera utilisé.", + "LabelServerNameHelp": "Ce nom sera utilisé pour identifier le serveur. Sinon le nom d'ordinateur sera utilisé.", "LabelGroupMoviesIntoCollections": "Grouper les films en collections", "LabelGroupMoviesIntoCollectionsHelp": "Dans l'affichage des listes de films, les films faisant partie d'une collection seront affichés comme un élément groupé.", "LabelH264Crf": "CRF d'encodage H264 :", diff --git a/src/strings/he.json b/src/strings/he.json index bc806a4387..16bf46af0e 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -204,7 +204,7 @@ "LabelFailed": "נכשל", "LabelFinish": "סיים", "LabelFriendlyServerName": "שם שרת ידידותי:", - "LabelFriendlyServerNameHelp": "השם יתן לזיהוי השרת. אם מושאר ריק, שם השרת יהיה שם המחשב.", + "LabelServerNameHelp": "השם יתן לזיהוי השרת. אם מושאר ריק, שם השרת יהיה שם המחשב.", "LabelKeepUpTo": "שמור עד ל:", "LabelLanguage": "שפה:", "LabelLocalHttpServerPortNumber": "מספר פורט HTTP מקומי", diff --git a/src/strings/hr.json b/src/strings/hr.json index 1b311e536e..795caa0c47 100644 --- a/src/strings/hr.json +++ b/src/strings/hr.json @@ -441,7 +441,7 @@ "LabelForgotPasswordUsernameHelp": "Unesite korisničko ime, ako se sjećate.", "LabelFriendlyName": "Prijateljsko ime", "LabelFriendlyServerName": "Prijateljsko ime servera:", - "LabelFriendlyServerNameHelp": "Ovo ime će se koristiti za identifikaciju servera. Ako ostavite prazno, ime računala će se koristi kao identifikator.", + "LabelServerNameHelp": "Ovo ime će se koristiti za identifikaciju servera. Ako ostavite prazno, ime računala će se koristi kao identifikator.", "LabelGroupMoviesIntoCollections": "Grupiraj filmove u kolekciju", "LabelGroupMoviesIntoCollectionsHelp": "Kada se prikazuje lista filmova, filmovi koji pripadaju kolekciji biti će prikazani kao jedna stavka.", "LabelH264Crf": "H264 kodiranje CRF:", diff --git a/src/strings/hu.json b/src/strings/hu.json index 8e0a17f3d1..13c4753171 100644 --- a/src/strings/hu.json +++ b/src/strings/hu.json @@ -922,7 +922,7 @@ "LabelFont": "Betűtípus:", "LabelFormat": "Formátum:", "LabelFriendlyName": "Könnyen megjegyezhető név:", - "LabelFriendlyServerNameHelp": "Ez a név kerül a Szerver azonosítására. Ha üresen marad, a számítógép neve kerül felhasználásra.", + "LabelServerNameHelp": "Ez a név kerül a Szerver azonosítására. Ha üresen marad, a számítógép neve kerül felhasználásra.", "LabelGroupMoviesIntoCollectionsHelp": "A filmlisták megjelenítésekor a gyűjteményhez tartozó filmek egy csoportos elemként jelennek meg.", "LabelH264Crf": "H264 encoding CRF:", "LabelHomeNetworkQuality": "Otthoni hálózat minősége:", diff --git a/src/strings/it.json b/src/strings/it.json index 3888034e46..3f0b5e5c13 100644 --- a/src/strings/it.json +++ b/src/strings/it.json @@ -604,7 +604,7 @@ "LabelFormat": "Formato:", "LabelFriendlyName": "Nome Condiviso:", "LabelFriendlyServerName": "Nome condiviso del server:", - "LabelFriendlyServerNameHelp": "Questo nome è usato per identificare il server sulla rete.Se lasciato vuoto verra usato il nome del pc", + "LabelServerNameHelp": "Questo nome è usato per identificare il server sulla rete.Se lasciato vuoto verra usato il nome del pc", "LabelGroupMoviesIntoCollections": "Raggruppa i film nelle collezioni", "LabelGroupMoviesIntoCollectionsHelp": "Quando si visualizzano le liste di film, quelli appartenenti ad una collezione saranno visualizzati come un elemento raggruppato.", "LabelH264Crf": "CRF di codifica H264:", diff --git a/src/strings/kk.json b/src/strings/kk.json index 4dbe2d78f0..d1c9a4745b 100644 --- a/src/strings/kk.json +++ b/src/strings/kk.json @@ -639,7 +639,7 @@ "LabelFormat": "Pishim:", "LabelFriendlyName": "Túsinikti ataý:", "LabelFriendlyServerName": "Serverdiń ońaı aty:", - "LabelFriendlyServerNameHelp": "Bul ataý osy serverdi anyqtaý úshin paıdalanylady. Eger óris bos qaldyrylsa, kompúter aty paıdalanylady.", + "LabelServerNameHelp": "Bul ataý osy serverdi anyqtaý úshin paıdalanylady. Eger óris bos qaldyrylsa, kompúter aty paıdalanylady.", "LabelGroupMoviesIntoCollections": "Jıyntyqtar ishindegi fılmderdi toptastyrý", "LabelGroupMoviesIntoCollectionsHelp": "Fılm tizimderin beınelegen kezde jıyntyqqa kiretin fılmder toptalǵan biryńǵaı tarmaq bolyp kórsetiledi.", "LabelH264Crf": "H264 kodtaý CRF máni:", diff --git a/src/strings/ko.json b/src/strings/ko.json index 4b7a4e6213..3995d12854 100644 --- a/src/strings/ko.json +++ b/src/strings/ko.json @@ -352,7 +352,7 @@ "LabelFormat": "형식:", "LabelFriendlyName": "별칭", "LabelFriendlyServerName": "알기쉬운 서버 이름:", - "LabelFriendlyServerNameHelp": "이 이름은 서버를 구분하는데 사용합니다. 비워두면 컴퓨터 이름을 사용합니다.", + "LabelServerNameHelp": "이 이름은 서버를 구분하는데 사용합니다. 비워두면 컴퓨터 이름을 사용합니다.", "LabelGroupMoviesIntoCollections": "컬렉션으로 영화 묶기", "LabelGroupMoviesIntoCollectionsHelp": "영화 목록을 표시할 때 컬렉션에 포함된 영화가 한 개로 묶여진 항목으로 보여줍니다.", "LabelHardwareAccelerationType": "하드웨어 가속:", diff --git a/src/strings/lt-lt.json b/src/strings/lt-lt.json index 6bf689f8b0..62e9b1117a 100644 --- a/src/strings/lt-lt.json +++ b/src/strings/lt-lt.json @@ -214,7 +214,7 @@ "LabelFinish": "Baigti", "LabelFriendlyName": "Draugiškas pavadinimas:", "LabelFriendlyServerName": "Draugiškas serverio pavadinimas:", - "LabelFriendlyServerNameHelp": "Šis pavadinimas bus naudojamas serverio identifikavimui. Palikus tuščią bus naudojamas kompiuterio pavadinimas.", + "LabelServerNameHelp": "Šis pavadinimas bus naudojamas serverio identifikavimui. Palikus tuščią bus naudojamas kompiuterio pavadinimas.", "LabelGroupMoviesIntoCollections": "Grupuoti filmus į kolekcijas", "LabelGroupMoviesIntoCollectionsHelp": "Rodant filmų sąrašą filmai iš kolekcijos bus rodomi kaip vienas elementas.", "LabelHttpsPort": "Vietinis HTTPS porto numeris:", diff --git a/src/strings/nb.json b/src/strings/nb.json index f248109aa2..45c36cc0b7 100644 --- a/src/strings/nb.json +++ b/src/strings/nb.json @@ -502,7 +502,7 @@ "LabelForgotPasswordUsernameHelp": "Skriv inn ditt brukernavn, hvis du husker det.", "LabelFriendlyName": "Vennlig navn", "LabelFriendlyServerName": "Vennlig server navn:", - "LabelFriendlyServerNameHelp": "Dette navnet vil bli brukt for å identifisere denne serveren. Hvis feltet er tomt, vil maskinens navn bli brukt.", + "LabelServerNameHelp": "Dette navnet vil bli brukt for å identifisere denne serveren. Hvis feltet er tomt, vil maskinens navn bli brukt.", "LabelGroupMoviesIntoCollections": "Gruppér filmer i samlinger", "LabelGroupMoviesIntoCollectionsHelp": "Ved visning av filmlister vil filmer som tilhører en samling bli vist som ett gruppeelement.", "LabelH264Crf": "H264 enkoding CRF:", diff --git a/src/strings/nl.json b/src/strings/nl.json index bdcf38efa9..837a4ac5fc 100644 --- a/src/strings/nl.json +++ b/src/strings/nl.json @@ -600,7 +600,7 @@ "LabelFormat": "Formaat:", "LabelFriendlyName": "Gebruiksvriendelijke naam:", "LabelFriendlyServerName": "Aangepaste servernaam", - "LabelFriendlyServerNameHelp": "Deze naam wordt gebruikt om deze server te identificeren. Indien leeg gelaten, zal de naam van de computer worden gebruikt.", + "LabelServerNameHelp": "Deze naam wordt gebruikt om deze server te identificeren. Indien leeg gelaten, zal de naam van de computer worden gebruikt.", "LabelGroupMoviesIntoCollections": "Groepeer films in collecties", "LabelGroupMoviesIntoCollectionsHelp": "Bij de weergave van film lijsten, zullen films die tot een collectie behoren worden weergegeven als een gegroepeerd object.", "LabelH264EncodingPreset": "H264 codering preset:", diff --git a/src/strings/pl.json b/src/strings/pl.json index e7f380f42f..a041a32c6d 100644 --- a/src/strings/pl.json +++ b/src/strings/pl.json @@ -637,7 +637,7 @@ "LabelForgotPasswordUsernameHelp": "Podaj nazwę użytkownika, jeśli pamiętasz.", "LabelFriendlyName": "Przyjazna nazwa:", "LabelFriendlyServerName": "Przyjazna nazwa serwera:", - "LabelFriendlyServerNameHelp": "Ta nazwa będzie użyta do identyfikacji serwera. Jeżeli zostawione puste, użyta będzie nazwa komputera.", + "LabelServerNameHelp": "Ta nazwa będzie użyta do identyfikacji serwera. Jeżeli zostawione puste, użyta będzie nazwa komputera.", "LabelGroupMoviesIntoCollections": "Grupuj filmy w kolekcje", "LabelGroupMoviesIntoCollectionsHelp": "Podczas wyświetlania listy filmów, filmy należące do kolekcji będą wyświetlone jako jedna zgrupowana pozycja.", "LabelH264Crf": "CRF kodowania H264:", diff --git a/src/strings/pt-br.json b/src/strings/pt-br.json index b71b3b8c0c..8a0a1c6b91 100644 --- a/src/strings/pt-br.json +++ b/src/strings/pt-br.json @@ -621,7 +621,7 @@ "LabelFormat": "Formato:", "LabelFriendlyName": "Nome amigável:", "LabelFriendlyServerName": "Nome amigável do servidor:", - "LabelFriendlyServerNameHelp": "Este nome será usado para identificar este servidor. Se deixado em branco, será usado o nome do computador.", + "LabelServerNameHelp": "Este nome será usado para identificar este servidor. Se deixado em branco, será usado o nome do computador.", "LabelGroupMoviesIntoCollections": "Agrupar filmes em coletâneas", "LabelGroupMoviesIntoCollectionsHelp": "Ao exibir listas de filmes, filmes que pertençam a uma coletânea serão exibidos como um único item agrupado.", "LabelH264Crf": "CRF de codificação H264:", diff --git a/src/strings/pt-pt.json b/src/strings/pt-pt.json index 2638b1cab9..2879604c45 100644 --- a/src/strings/pt-pt.json +++ b/src/strings/pt-pt.json @@ -362,7 +362,7 @@ "LabelFormat": "Formato:", "LabelFriendlyName": "Nome amigável", "LabelFriendlyServerName": "Nome amigável do servidor:", - "LabelFriendlyServerNameHelp": "Será usado este nome para identificar o servidor. Se não for preenchido, será usado o nome do computador.", + "LabelServerNameHelp": "Será usado este nome para identificar o servidor. Se não for preenchido, será usado o nome do computador.", "LabelGroupMoviesIntoCollections": "Agrupar filmes nas coleções", "LabelGroupMoviesIntoCollectionsHelp": "Ao exibir listas de filmes, filmes que pertençam a uma coleção serão exibidos como um único item agrupado.", "LabelHardwareAccelerationType": "Aceleração de hardware:", diff --git a/src/strings/ru.json b/src/strings/ru.json index b8f02a9b84..b308de0068 100644 --- a/src/strings/ru.json +++ b/src/strings/ru.json @@ -639,7 +639,7 @@ "LabelFormat": "Формат:", "LabelFriendlyName": "Понятное имя:", "LabelFriendlyServerName": "Понятное имя сервера:", - "LabelFriendlyServerNameHelp": "Данное имя используется для распознавания данного сервера. Если не заполнять, то будет использовано имя компьютера.", + "LabelServerNameHelp": "Данное имя используется для распознавания данного сервера. Если не заполнять, то будет использовано имя компьютера.", "LabelGroupMoviesIntoCollections": "Группировать фильмы внутрь коллекций", "LabelGroupMoviesIntoCollectionsHelp": "При отображении списка фильмов, элементы, принадлежащие к одной коллекции будут отображаться как единый сгруппированный элемент.", "LabelH264Crf": "Значение CRF H264-кодирования:", diff --git a/src/strings/sk.json b/src/strings/sk.json index 66df365bd7..31d0e00d61 100644 --- a/src/strings/sk.json +++ b/src/strings/sk.json @@ -392,7 +392,7 @@ "LabelForgotPasswordUsernameHelp": "Zadajte svoje používateľské meno, ak si ho pamätáte.", "LabelFormat": "Formát:", "LabelFriendlyServerName": "Názov servera:", - "LabelFriendlyServerNameHelp": "Toto meno bude použité na identifikáciu servera. Ak ostane prázdne, bude použitý názov počítača.", + "LabelServerNameHelp": "Toto meno bude použité na identifikáciu servera. Ak ostane prázdne, bude použitý názov počítača.", "LabelGroupMoviesIntoCollections": "Zoskupiť filmy do kolekcií.", "LabelGroupMoviesIntoCollectionsHelp": "Pri zobrazení zoznamu filmov budú filmy patriace do kolekcie zobrazené ako jedna zoskupená položka.", "LabelHardwareAccelerationType": "Hardvérová akcelerácia:", diff --git a/src/strings/sv.json b/src/strings/sv.json index 833ca4eb61..6c4aec02e7 100644 --- a/src/strings/sv.json +++ b/src/strings/sv.json @@ -591,7 +591,7 @@ "LabelForgotPasswordUsernameHelp": "Skriv ditt användarnamn, om du kommer ihåg det.", "LabelFriendlyName": "Visningsnamn", "LabelFriendlyServerName": "Ditt önskade servernamn:", - "LabelFriendlyServerNameHelp": "Det här namnet används för att identifiera servern, om det lämnas tomt kommer datorns namn att användas.", + "LabelServerNameHelp": "Det här namnet används för att identifiera servern, om det lämnas tomt kommer datorns namn att användas.", "LabelGroupMoviesIntoCollections": "Gruppera filmer i samlingsboxar", "LabelGroupMoviesIntoCollectionsHelp": "I filmlistor visas filmer som ingår i en samlingsbox som ett enda objekt.", "LabelH264Crf": "H264-omkodning CRF:", diff --git a/src/strings/zh-cn.json b/src/strings/zh-cn.json index 1ce9d7ba3b..179b4b7e42 100644 --- a/src/strings/zh-cn.json +++ b/src/strings/zh-cn.json @@ -599,7 +599,7 @@ "LabelFormat": "格式:", "LabelFriendlyName": "好记的名称:", "LabelFriendlyServerName": "好记的服务器名称:", - "LabelFriendlyServerNameHelp": "此名称将用做服务器名,如果留空,将使用计算机名。", + "LabelServerNameHelp": "此名称将用做服务器名,如果留空,将使用计算机名。", "LabelGroupMoviesIntoCollections": "批量添加电影到收藏", "LabelGroupMoviesIntoCollectionsHelp": "显示电影列表时,属于一个收藏的电影将显示为一个分组。", "LabelH264Crf": "H264 编码速率控制", diff --git a/src/strings/zh-hk.json b/src/strings/zh-hk.json index d38b4728c4..40939c2376 100644 --- a/src/strings/zh-hk.json +++ b/src/strings/zh-hk.json @@ -124,7 +124,7 @@ "LabelFanartApiKey": "個人 API 鎖匙:", "LabelFinish": "完成", "LabelFriendlyServerName": "友好伺服器名稱:", - "LabelFriendlyServerNameHelp": "名稱用於識辨伺服器。如果留空,將使用本機(伺服器)名稱。", + "LabelServerNameHelp": "名稱用於識辨伺服器。如果留空,將使用本機(伺服器)名稱。", "LabelHttpsPort": "本地 https 連接埠號碼:", "LabelHttpsPortHelp": "TCP 連接埠號碼應綁定到 Jellyfin https 伺服器。", "LabelImageFetchersHelp": "啟用媒體圖片獲取程式的優先次序", diff --git a/src/strings/zh-tw.json b/src/strings/zh-tw.json index a554177ac5..9cad4bfcf5 100644 --- a/src/strings/zh-tw.json +++ b/src/strings/zh-tw.json @@ -120,7 +120,7 @@ "LabelEveryXMinutes": "每:", "LabelFinish": "完成", "LabelFriendlyServerName": "友好伺服器名稱:", - "LabelFriendlyServerNameHelp": "此名稱將用於標識伺服器。如果留空,計算機名稱將被使用。", + "LabelServerNameHelp": "此名稱將用於標識伺服器。如果留空,計算機名稱將被使用。", "LabelLanguage": "語言:", "LabelMaxBackdropsPerItem": "每個項目背景的最大數目:", "LabelMaxParentalRating": "最大允許的家長評級:", From 92555c36ce1b21f491a8b70e3ef4c492cdb417ed Mon Sep 17 00:00:00 2001 From: dkanada Date: Fri, 22 Mar 2019 15:48:05 -0700 Subject: [PATCH 154/220] remove unused string --- src/strings/ar.json | 1 - src/strings/bg-bg.json | 1 - src/strings/ca.json | 1 - src/strings/cs.json | 1 - src/strings/da.json | 1 - src/strings/de.json | 1 - src/strings/el.json | 1 - src/strings/en-us.json | 1 - src/strings/es-mx.json | 1 - src/strings/es.json | 1 - src/strings/fr.json | 1 - src/strings/he.json | 1 - src/strings/hr.json | 1 - src/strings/hu.json | 1 - src/strings/it.json | 1 - src/strings/kk.json | 1 - src/strings/ko.json | 1 - src/strings/lt-lt.json | 1 - src/strings/nb.json | 1 - src/strings/nl.json | 1 - src/strings/pl.json | 1 - src/strings/pt-br.json | 1 - src/strings/pt-pt.json | 1 - src/strings/ru.json | 1 - src/strings/sk.json | 1 - src/strings/sv.json | 1 - src/strings/zh-cn.json | 1 - src/strings/zh-hk.json | 1 - src/strings/zh-tw.json | 1 - 29 files changed, 29 deletions(-) diff --git a/src/strings/ar.json b/src/strings/ar.json index d5abe0e578..1473ae5915 100644 --- a/src/strings/ar.json +++ b/src/strings/ar.json @@ -404,7 +404,6 @@ "LabelForgotPasswordUsernameHelp": "أدخل اسم المستخدم الخاص بك، إن كنت تتذكرها", "LabelFormat": "الصيغة:", "LabelFriendlyName": "اسم مخصوص لك", - "LabelFriendlyServerName": "اسم الخادم الميسر:", "LabelServerNameHelp": "هذا الاسم يسيتخدم للتعرف على الخادم. إن ترك خالٍ، فإن اسم الحاسوب سوف يستخدم.", "LabelGroupMoviesIntoCollections": "تجميع الأفلام إلى مجاميع", "LabelGroupMoviesIntoCollectionsHelp": "عند استعراض قوائم الأفلام، فإن الأفلام التي تنتمي إلى مجموعة واحدة ستظهر كعنصر جامع.", diff --git a/src/strings/bg-bg.json b/src/strings/bg-bg.json index c3af936019..be91a323e2 100644 --- a/src/strings/bg-bg.json +++ b/src/strings/bg-bg.json @@ -361,7 +361,6 @@ "LabelFinish": "Готово", "LabelFont": "Шрифт:", "LabelForgotPasswordUsernameHelp": "Въведете потребителското си име, ако го помните.", - "LabelFriendlyServerName": "Име на сървъра:", "LabelGroupMoviesIntoCollections": "Групиране на филмите в колекции", "LabelHardwareAccelerationType": "Хардуерно ускорение:", "LabelHomeNetworkQuality": "Качество на домашната мрежа:", diff --git a/src/strings/ca.json b/src/strings/ca.json index f175917e81..0da5ac93bc 100644 --- a/src/strings/ca.json +++ b/src/strings/ca.json @@ -338,7 +338,6 @@ "LabelFanartApiKey": "Clau api personal:", "LabelFinish": "Finalitzar", "LabelFriendlyName": "Nom amistós", - "LabelFriendlyServerName": "Nom amistós del servidor:", "LabelServerNameHelp": "El nom servirà per identificar aquest servidor. Si es deixa en blanc s'emprarà el nom de l'ordinador.", "LabelGroupMoviesIntoCollections": "Agrupa pel·lícules a col·leccions", "LabelHomeScreenSectionValue": "Secció {0} de la pàgina d'inici:", diff --git a/src/strings/cs.json b/src/strings/cs.json index cd5e55fcb9..7fc1dc677f 100644 --- a/src/strings/cs.json +++ b/src/strings/cs.json @@ -540,7 +540,6 @@ "LabelForgotPasswordUsernameHelp": "Zadej své uživatelské jméno, jestliže se má pamatovat.", "LabelFormat": "Formát:", "LabelFriendlyName": "Přívětivý název", - "LabelFriendlyServerName": "Název serveru:", "LabelServerNameHelp": "Toto jméno bude použito jako identifikace serveru, ponecháte-li prázdné bude použit název počítače.", "LabelGroupMoviesIntoCollections": "Seskupit filmy do kolekcí.", "LabelGroupMoviesIntoCollectionsHelp": "Při zobrazení seznamů filmu, budou filmy patřící do kolekce, zobrazeny jako jedna položka.", diff --git a/src/strings/da.json b/src/strings/da.json index c3fc4f224e..12dff74d51 100644 --- a/src/strings/da.json +++ b/src/strings/da.json @@ -497,7 +497,6 @@ "LabelFinish": "Afslut", "LabelForgotPasswordUsernameHelp": "Indtast dit brugernavn, hvis du kan huske det.", "LabelFriendlyName": "System venligt navn:", - "LabelFriendlyServerName": "Nemt servernavn:", "LabelServerNameHelp": "Dette navn bruges til at identificere serveren. Hvis det ikke udfyldes, bruges computerens navn.", "LabelGroupMoviesIntoCollections": "Grupper film i samlinger", "LabelGroupMoviesIntoCollectionsHelp": "Film i samlinger vil blive vist som en samlet enhed i filmlister.", diff --git a/src/strings/de.json b/src/strings/de.json index 334c0f507e..a34911a35f 100644 --- a/src/strings/de.json +++ b/src/strings/de.json @@ -597,7 +597,6 @@ "LabelFont": "Schriftart:", "LabelForgotPasswordUsernameHelp": "Bitte gib deinen Benutzernamen ein, falls du dich daran erinnerst.", "LabelFriendlyName": "Benutzerfreundlicher Name:", - "LabelFriendlyServerName": "Freundlicher Servername:", "LabelServerNameHelp": "Dieser Name wird benutzt um diesen Server zu identifizieren. Wenn leer gelassen, wird der Computername benutzt.", "LabelGroupMoviesIntoCollections": "Gruppiere Filme in Collections", "LabelGroupMoviesIntoCollectionsHelp": "Wenn Filmlisten angezeigt werden, dann werden Filme, die zu einer Collection gehören, als ein gruppiertes Element angezeigt.", diff --git a/src/strings/el.json b/src/strings/el.json index 064e686d61..94e904ed9a 100644 --- a/src/strings/el.json +++ b/src/strings/el.json @@ -550,7 +550,6 @@ "LabelForgotPasswordUsernameHelp": "Εισαγωγή όνομα χρήστη,αν το θυμάστε.", "LabelFormat": "Φορμάτ:", "LabelFriendlyName": "Φιλικό όνομα", - "LabelFriendlyServerName": "Όνομα διακομιστή:", "LabelServerNameHelp": "Αυτό το όνομα θα χρησιμοποιηθεί για την αναγνώριση αυτού του διακομιστή. Αν παραμείνει κενό, θα χρησιμοποιηθεί το όνομα του υπολογιστή.", "LabelGroupMoviesIntoCollections": "Ομαδοποιήστε ταινίες σε συλλογές", "LabelGroupMoviesIntoCollectionsHelp": "Όταν προβάλλετε λίστες ταινιών, οι ταινίες που ανήκουν σε μια συλλογή θα εμφανίζονται ως ένα ομαδοποιημένο αντικείμενο.", diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 561d1c8e79..249d958900 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -643,7 +643,6 @@ "LabelForgotPasswordUsernameHelp": "Enter your username, if you remember it.", "LabelFormat": "Format:", "LabelFriendlyName": "Friendly name:", - "LabelFriendlyServerName": "Friendly server name:", "LabelServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", "LabelGroupMoviesIntoCollections": "Group movies into collections", "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies belonging to a collection will be displayed as one grouped item.", diff --git a/src/strings/es-mx.json b/src/strings/es-mx.json index f97169e695..03c534f4e3 100644 --- a/src/strings/es-mx.json +++ b/src/strings/es-mx.json @@ -624,7 +624,6 @@ "LabelForgotPasswordUsernameHelp": "Introduce tu nombre de usuario, si lo recuerdas.", "LabelFormat": "Formato:", "LabelFriendlyName": "Nombre amistoso:", - "LabelFriendlyServerName": "Nombre amigable del servidor:", "LabelServerNameHelp": "Este nombre será usado para identificar este servidor. Si se deja en blanco, se usará el nombre de la computadora.", "LabelGroupMoviesIntoCollections": "Agrupar películas en colecciones", "LabelGroupMoviesIntoCollectionsHelp": "Cuando se muestran listados de películas, las películas que pertenecen a una colección serán mostradas agrupadas en un solo ítem.", diff --git a/src/strings/es.json b/src/strings/es.json index d303394353..0922ecaa42 100644 --- a/src/strings/es.json +++ b/src/strings/es.json @@ -563,7 +563,6 @@ "LabelForgotPasswordUsernameHelp": "Introduce tu nombre de usuario, si te acuerdas.", "LabelFormat": "Formato:", "LabelFriendlyName": "Nombre amigable:", - "LabelFriendlyServerName": "Nombre informal del servidor:", "LabelServerNameHelp": "Este nombre se podrá utilizar para identificar este servidor. Si se deja en blanco se usará el nombre del ordenador.", "LabelGroupMoviesIntoCollections": "Agrupar películas en colecciones", "LabelGroupMoviesIntoCollectionsHelp": "Cuando se muestran las listas de películas, las películas pertenecientes a una colección se mostrarán como un elemento agrupado.", diff --git a/src/strings/fr.json b/src/strings/fr.json index 8cbd6f1f10..08fdc280d1 100644 --- a/src/strings/fr.json +++ b/src/strings/fr.json @@ -622,7 +622,6 @@ "LabelForgotPasswordUsernameHelp": "Saisissez votre nom d'utilisateur, si vous vous en souvenez.", "LabelFormat": "Format :", "LabelFriendlyName": "Nom d'affichage :", - "LabelFriendlyServerName": "Surnom du serveur :", "LabelServerNameHelp": "Ce nom sera utilisé pour identifier le serveur. Sinon le nom d'ordinateur sera utilisé.", "LabelGroupMoviesIntoCollections": "Grouper les films en collections", "LabelGroupMoviesIntoCollectionsHelp": "Dans l'affichage des listes de films, les films faisant partie d'une collection seront affichés comme un élément groupé.", diff --git a/src/strings/he.json b/src/strings/he.json index 16bf46af0e..9487fc63f7 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -203,7 +203,6 @@ "LabelEveryXMinutes": "כל:", "LabelFailed": "נכשל", "LabelFinish": "סיים", - "LabelFriendlyServerName": "שם שרת ידידותי:", "LabelServerNameHelp": "השם יתן לזיהוי השרת. אם מושאר ריק, שם השרת יהיה שם המחשב.", "LabelKeepUpTo": "שמור עד ל:", "LabelLanguage": "שפה:", diff --git a/src/strings/hr.json b/src/strings/hr.json index 795caa0c47..f7b64f7048 100644 --- a/src/strings/hr.json +++ b/src/strings/hr.json @@ -440,7 +440,6 @@ "LabelFinish": "Kraj", "LabelForgotPasswordUsernameHelp": "Unesite korisničko ime, ako se sjećate.", "LabelFriendlyName": "Prijateljsko ime", - "LabelFriendlyServerName": "Prijateljsko ime servera:", "LabelServerNameHelp": "Ovo ime će se koristiti za identifikaciju servera. Ako ostavite prazno, ime računala će se koristi kao identifikator.", "LabelGroupMoviesIntoCollections": "Grupiraj filmove u kolekciju", "LabelGroupMoviesIntoCollectionsHelp": "Kada se prikazuje lista filmova, filmovi koji pripadaju kolekciji biti će prikazani kao jedna stavka.", diff --git a/src/strings/hu.json b/src/strings/hu.json index 13c4753171..abf0c730f0 100644 --- a/src/strings/hu.json +++ b/src/strings/hu.json @@ -278,7 +278,6 @@ "LabelEveryXMinutes": "Minden:", "LabelFinish": "Befejez", "LabelForgotPasswordUsernameHelp": "Add meg a felhasználóneved, ha emlékszel rá.", - "LabelFriendlyServerName": "Könnyen megjegyezhető szerver név:", "LabelGroupMoviesIntoCollections": "Filmek csoportosítása gyűjteményekbe", "LabelH264EncodingPreset": "H264 kódolási beállítások:", "LabelHardwareAccelerationType": "Hardveres gyorsítás:", diff --git a/src/strings/it.json b/src/strings/it.json index 3f0b5e5c13..7aa1abb88c 100644 --- a/src/strings/it.json +++ b/src/strings/it.json @@ -603,7 +603,6 @@ "LabelForgotPasswordUsernameHelp": "Inserisci il tuo nome utente, se te lo ricordi.", "LabelFormat": "Formato:", "LabelFriendlyName": "Nome Condiviso:", - "LabelFriendlyServerName": "Nome condiviso del server:", "LabelServerNameHelp": "Questo nome è usato per identificare il server sulla rete.Se lasciato vuoto verra usato il nome del pc", "LabelGroupMoviesIntoCollections": "Raggruppa i film nelle collezioni", "LabelGroupMoviesIntoCollectionsHelp": "Quando si visualizzano le liste di film, quelli appartenenti ad una collezione saranno visualizzati come un elemento raggruppato.", diff --git a/src/strings/kk.json b/src/strings/kk.json index d1c9a4745b..ddef0bf5a7 100644 --- a/src/strings/kk.json +++ b/src/strings/kk.json @@ -638,7 +638,6 @@ "LabelForgotPasswordUsernameHelp": "Eske salsańyz, paıdalanýshy atyńyzdy engizińiz.", "LabelFormat": "Pishim:", "LabelFriendlyName": "Túsinikti ataý:", - "LabelFriendlyServerName": "Serverdiń ońaı aty:", "LabelServerNameHelp": "Bul ataý osy serverdi anyqtaý úshin paıdalanylady. Eger óris bos qaldyrylsa, kompúter aty paıdalanylady.", "LabelGroupMoviesIntoCollections": "Jıyntyqtar ishindegi fılmderdi toptastyrý", "LabelGroupMoviesIntoCollectionsHelp": "Fılm tizimderin beınelegen kezde jıyntyqqa kiretin fılmder toptalǵan biryńǵaı tarmaq bolyp kórsetiledi.", diff --git a/src/strings/ko.json b/src/strings/ko.json index 3995d12854..dcc386abbd 100644 --- a/src/strings/ko.json +++ b/src/strings/ko.json @@ -351,7 +351,6 @@ "LabelForgotPasswordUsernameHelp": "기억하고 있다면, 사용자명을 입력하세요.", "LabelFormat": "형식:", "LabelFriendlyName": "별칭", - "LabelFriendlyServerName": "알기쉬운 서버 이름:", "LabelServerNameHelp": "이 이름은 서버를 구분하는데 사용합니다. 비워두면 컴퓨터 이름을 사용합니다.", "LabelGroupMoviesIntoCollections": "컬렉션으로 영화 묶기", "LabelGroupMoviesIntoCollectionsHelp": "영화 목록을 표시할 때 컬렉션에 포함된 영화가 한 개로 묶여진 항목으로 보여줍니다.", diff --git a/src/strings/lt-lt.json b/src/strings/lt-lt.json index 62e9b1117a..a9ce1629a3 100644 --- a/src/strings/lt-lt.json +++ b/src/strings/lt-lt.json @@ -213,7 +213,6 @@ "LabelFanartApiKeyHelp": "Fanų meno užklausos be asmeninio API rakto pateiks paveikslus, kurie buvo patvirtinti seniau nei prieš 7 dienas. Su asmeniniu API raktu šis laikas sumažėja iki 48 valandų, o jei esate fanų meno VIP narys, šis laikas dar sumažės iki maždaug 10 minučių.", "LabelFinish": "Baigti", "LabelFriendlyName": "Draugiškas pavadinimas:", - "LabelFriendlyServerName": "Draugiškas serverio pavadinimas:", "LabelServerNameHelp": "Šis pavadinimas bus naudojamas serverio identifikavimui. Palikus tuščią bus naudojamas kompiuterio pavadinimas.", "LabelGroupMoviesIntoCollections": "Grupuoti filmus į kolekcijas", "LabelGroupMoviesIntoCollectionsHelp": "Rodant filmų sąrašą filmai iš kolekcijos bus rodomi kaip vienas elementas.", diff --git a/src/strings/nb.json b/src/strings/nb.json index 45c36cc0b7..c2b55a9382 100644 --- a/src/strings/nb.json +++ b/src/strings/nb.json @@ -501,7 +501,6 @@ "LabelFinish": "Slutt", "LabelForgotPasswordUsernameHelp": "Skriv inn ditt brukernavn, hvis du husker det.", "LabelFriendlyName": "Vennlig navn", - "LabelFriendlyServerName": "Vennlig server navn:", "LabelServerNameHelp": "Dette navnet vil bli brukt for å identifisere denne serveren. Hvis feltet er tomt, vil maskinens navn bli brukt.", "LabelGroupMoviesIntoCollections": "Gruppér filmer i samlinger", "LabelGroupMoviesIntoCollectionsHelp": "Ved visning av filmlister vil filmer som tilhører en samling bli vist som ett gruppeelement.", diff --git a/src/strings/nl.json b/src/strings/nl.json index 837a4ac5fc..8057cf2ead 100644 --- a/src/strings/nl.json +++ b/src/strings/nl.json @@ -599,7 +599,6 @@ "LabelForgotPasswordUsernameHelp": "Vul uw gebruikersnaam in, als u deze weet.", "LabelFormat": "Formaat:", "LabelFriendlyName": "Gebruiksvriendelijke naam:", - "LabelFriendlyServerName": "Aangepaste servernaam", "LabelServerNameHelp": "Deze naam wordt gebruikt om deze server te identificeren. Indien leeg gelaten, zal de naam van de computer worden gebruikt.", "LabelGroupMoviesIntoCollections": "Groepeer films in collecties", "LabelGroupMoviesIntoCollectionsHelp": "Bij de weergave van film lijsten, zullen films die tot een collectie behoren worden weergegeven als een gegroepeerd object.", diff --git a/src/strings/pl.json b/src/strings/pl.json index a041a32c6d..dae806aa6b 100644 --- a/src/strings/pl.json +++ b/src/strings/pl.json @@ -636,7 +636,6 @@ "LabelFont": "Czcionka:", "LabelForgotPasswordUsernameHelp": "Podaj nazwę użytkownika, jeśli pamiętasz.", "LabelFriendlyName": "Przyjazna nazwa:", - "LabelFriendlyServerName": "Przyjazna nazwa serwera:", "LabelServerNameHelp": "Ta nazwa będzie użyta do identyfikacji serwera. Jeżeli zostawione puste, użyta będzie nazwa komputera.", "LabelGroupMoviesIntoCollections": "Grupuj filmy w kolekcje", "LabelGroupMoviesIntoCollectionsHelp": "Podczas wyświetlania listy filmów, filmy należące do kolekcji będą wyświetlone jako jedna zgrupowana pozycja.", diff --git a/src/strings/pt-br.json b/src/strings/pt-br.json index 8a0a1c6b91..a13ff50254 100644 --- a/src/strings/pt-br.json +++ b/src/strings/pt-br.json @@ -620,7 +620,6 @@ "LabelForgotPasswordUsernameHelp": "Digite o nome de seu usuário, se lembrar.", "LabelFormat": "Formato:", "LabelFriendlyName": "Nome amigável:", - "LabelFriendlyServerName": "Nome amigável do servidor:", "LabelServerNameHelp": "Este nome será usado para identificar este servidor. Se deixado em branco, será usado o nome do computador.", "LabelGroupMoviesIntoCollections": "Agrupar filmes em coletâneas", "LabelGroupMoviesIntoCollectionsHelp": "Ao exibir listas de filmes, filmes que pertençam a uma coletânea serão exibidos como um único item agrupado.", diff --git a/src/strings/pt-pt.json b/src/strings/pt-pt.json index 2879604c45..87dadc3f12 100644 --- a/src/strings/pt-pt.json +++ b/src/strings/pt-pt.json @@ -361,7 +361,6 @@ "LabelForgotPasswordUsernameHelp": "Digite o nome de seu utilizador, se lembrar.", "LabelFormat": "Formato:", "LabelFriendlyName": "Nome amigável", - "LabelFriendlyServerName": "Nome amigável do servidor:", "LabelServerNameHelp": "Será usado este nome para identificar o servidor. Se não for preenchido, será usado o nome do computador.", "LabelGroupMoviesIntoCollections": "Agrupar filmes nas coleções", "LabelGroupMoviesIntoCollectionsHelp": "Ao exibir listas de filmes, filmes que pertençam a uma coleção serão exibidos como um único item agrupado.", diff --git a/src/strings/ru.json b/src/strings/ru.json index b308de0068..3dbcf92fec 100644 --- a/src/strings/ru.json +++ b/src/strings/ru.json @@ -638,7 +638,6 @@ "LabelForgotPasswordUsernameHelp": "Введите имя пользователя, если помните его.", "LabelFormat": "Формат:", "LabelFriendlyName": "Понятное имя:", - "LabelFriendlyServerName": "Понятное имя сервера:", "LabelServerNameHelp": "Данное имя используется для распознавания данного сервера. Если не заполнять, то будет использовано имя компьютера.", "LabelGroupMoviesIntoCollections": "Группировать фильмы внутрь коллекций", "LabelGroupMoviesIntoCollectionsHelp": "При отображении списка фильмов, элементы, принадлежащие к одной коллекции будут отображаться как единый сгруппированный элемент.", diff --git a/src/strings/sk.json b/src/strings/sk.json index 31d0e00d61..a7580efb23 100644 --- a/src/strings/sk.json +++ b/src/strings/sk.json @@ -391,7 +391,6 @@ "LabelFont": "Písmo:", "LabelForgotPasswordUsernameHelp": "Zadajte svoje používateľské meno, ak si ho pamätáte.", "LabelFormat": "Formát:", - "LabelFriendlyServerName": "Názov servera:", "LabelServerNameHelp": "Toto meno bude použité na identifikáciu servera. Ak ostane prázdne, bude použitý názov počítača.", "LabelGroupMoviesIntoCollections": "Zoskupiť filmy do kolekcií.", "LabelGroupMoviesIntoCollectionsHelp": "Pri zobrazení zoznamu filmov budú filmy patriace do kolekcie zobrazené ako jedna zoskupená položka.", diff --git a/src/strings/sv.json b/src/strings/sv.json index 6c4aec02e7..c31b60e354 100644 --- a/src/strings/sv.json +++ b/src/strings/sv.json @@ -590,7 +590,6 @@ "LabelFont": "Typsnitt:", "LabelForgotPasswordUsernameHelp": "Skriv ditt användarnamn, om du kommer ihåg det.", "LabelFriendlyName": "Visningsnamn", - "LabelFriendlyServerName": "Ditt önskade servernamn:", "LabelServerNameHelp": "Det här namnet används för att identifiera servern, om det lämnas tomt kommer datorns namn att användas.", "LabelGroupMoviesIntoCollections": "Gruppera filmer i samlingsboxar", "LabelGroupMoviesIntoCollectionsHelp": "I filmlistor visas filmer som ingår i en samlingsbox som ett enda objekt.", diff --git a/src/strings/zh-cn.json b/src/strings/zh-cn.json index 179b4b7e42..a616f48e27 100644 --- a/src/strings/zh-cn.json +++ b/src/strings/zh-cn.json @@ -598,7 +598,6 @@ "LabelForgotPasswordUsernameHelp": "输入你的用户名,如果你还记得。", "LabelFormat": "格式:", "LabelFriendlyName": "好记的名称:", - "LabelFriendlyServerName": "好记的服务器名称:", "LabelServerNameHelp": "此名称将用做服务器名,如果留空,将使用计算机名。", "LabelGroupMoviesIntoCollections": "批量添加电影到收藏", "LabelGroupMoviesIntoCollectionsHelp": "显示电影列表时,属于一个收藏的电影将显示为一个分组。", diff --git a/src/strings/zh-hk.json b/src/strings/zh-hk.json index 40939c2376..d48664d513 100644 --- a/src/strings/zh-hk.json +++ b/src/strings/zh-hk.json @@ -123,7 +123,6 @@ "LabelFailed": "失敗", "LabelFanartApiKey": "個人 API 鎖匙:", "LabelFinish": "完成", - "LabelFriendlyServerName": "友好伺服器名稱:", "LabelServerNameHelp": "名稱用於識辨伺服器。如果留空,將使用本機(伺服器)名稱。", "LabelHttpsPort": "本地 https 連接埠號碼:", "LabelHttpsPortHelp": "TCP 連接埠號碼應綁定到 Jellyfin https 伺服器。", diff --git a/src/strings/zh-tw.json b/src/strings/zh-tw.json index 9cad4bfcf5..75bb58e41b 100644 --- a/src/strings/zh-tw.json +++ b/src/strings/zh-tw.json @@ -119,7 +119,6 @@ "LabelEvent": "事件:", "LabelEveryXMinutes": "每:", "LabelFinish": "完成", - "LabelFriendlyServerName": "友好伺服器名稱:", "LabelServerNameHelp": "此名稱將用於標識伺服器。如果留空,計算機名稱將被使用。", "LabelLanguage": "語言:", "LabelMaxBackdropsPerItem": "每個項目背景的最大數目:", From 4144d929e7d02cfd1380edeaae72f5297ab33e91 Mon Sep 17 00:00:00 2001 From: Vasily Date: Sat, 23 Mar 2019 23:47:31 -0700 Subject: [PATCH 155/220] Apply suggestions from code review adding justaman's fixes Co-Authored-By: LogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com> --- src/scripts/useredit.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/scripts/useredit.js b/src/scripts/useredit.js index 74d70ac0bf..e972627c88 100644 --- a/src/scripts/useredit.js +++ b/src/scripts/useredit.js @@ -36,8 +36,6 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, l } else { $(".disabledUserBanner", page).hide(); } - "Guest" == user.ConnectLinkType ? ($("#fldConnectInfo", page).hide(), - $("#txtUserName", page).prop("disabled", "disabled")) : ($("#txtUserName", page).prop("disabled", "").removeAttr("disabled"), if ("Guest" == user.ConnectLinkType) { $("#fldConnectInfo", page).hide(); $("#txtUserName", page).prop("disabled", "disabled"); From ef3166143a2d6a50b059ac3a809ba49667393e42 Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 23 Mar 2019 23:13:32 -0700 Subject: [PATCH 156/220] add custom strings for system info panel on dashboard --- src/controllers/dashboardgeneral.js | 8 ++++---- src/controllers/dashboardpage.js | 4 ++-- src/strings/en-us.json | 7 ++++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/controllers/dashboardgeneral.js b/src/controllers/dashboardgeneral.js index 6a3f80d3a2..c02717fdbb 100644 --- a/src/controllers/dashboardgeneral.js +++ b/src/controllers/dashboardgeneral.js @@ -2,15 +2,15 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb "use strict"; function loadPage(page, config, languageOptions, systemInfo) { - page.querySelector("#txtServerName").value = config.ServerName; + page.querySelector("#txtServerName").value = systemInfo.ServerName; if (systemInfo.CanLaunchWebBrowser) { page.querySelector("#fldRunWebAppAtStartup").classList.remove("hide"); } else { page.querySelector("#fldRunWebAppAtStartup").classList.add("hide"); } - page.querySelector("#txtCachePath").value = config.CachePath || ""; - $("#txtMetadataPath", page).val(config.MetadataPath || ""); - $("#txtMetadataNetworkPath", page).val(config.MetadataNetworkPath || ""); + page.querySelector("#txtCachePath").value = systemInfo.CachePath || ""; + $("#txtMetadataPath", page).val(systemInfo.InternalMetadataPath || ""); + $("#txtMetadataNetworkPath", page).val(systemInfo.MetadataNetworkPath || ""); $("#selectLocalizationLanguage", page).html(languageOptions.map(function(language) { return '" })).val(config.UICulture); diff --git a/src/controllers/dashboardpage.js b/src/controllers/dashboardpage.js index 5fb20f953c..c0a363d65c 100644 --- a/src/controllers/dashboardpage.js +++ b/src/controllers/dashboardpage.js @@ -177,9 +177,9 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa function reloadSystemInfo(view, apiClient) { apiClient.getSystemInfo().then(function (systemInfo) { - view.querySelector("#serverName").innerHTML = globalize.translate("LabelServerName", systemInfo.ServerName); + view.querySelector("#serverName").innerHTML = globalize.translate("DashboardServerName", systemInfo.ServerName); - var localizedVersion = globalize.translate("LabelVersionNumber", systemInfo.Version); + var localizedVersion = globalize.translate("DashboardVersionNumber", systemInfo.Version); if (systemInfo.SystemUpdateLevel && "Release" != systemInfo.SystemUpdateLevel) { localizedVersion += " " + globalize.translate("Option" + systemInfo.SystemUpdateLevel).toLowerCase(); } diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 249d958900..eda4b8805b 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -801,7 +801,7 @@ "LabelSeriesRecordingPath": "Series recording path (optional):", "LabelServerHost": "Host:", "LabelServerHostHelp": "192.168.1.100 or https://myserver.com", - "LabelServerName": "Server Name: {0}", + "LabelServerName": "Server name:", "LabelServerPort": "Port:", "LabelSimultaneousConnectionLimit": "Simultaneous stream limit:", "LabelSkin": "Skin:", @@ -866,9 +866,10 @@ "LabelValue": "Value:", "LabelVersion": "Version:", "LabelVersionInstalled": "{0} installed", - "LabelVersionNumber": "Version: {0}", + "DashboardVersionNumber": "Version: {0}", + "DashboardServerName": "Server: {0}", "LabelVideo": "Video:", - "LabelWeb": "Web", + "LabelWeb": "Web: ", "LabelXDlnaCap": "X-Dlna cap:", "LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.", "LabelXDlnaDoc": "X-Dlna doc:", From 6b1908227f4c092012bc0aa925b71f5db4b23544 Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 23 Mar 2019 23:30:19 -0700 Subject: [PATCH 157/220] update transcode path strings --- src/dashboard.html | 2 +- src/encodingsettings.html | 2 +- src/strings/ar.json | 2 -- src/strings/bg-bg.json | 1 - src/strings/ca.json | 2 -- src/strings/cs.json | 2 -- src/strings/da.json | 2 -- src/strings/de.json | 2 -- src/strings/el.json | 2 -- src/strings/en-us.json | 4 ++-- src/strings/es-mx.json | 2 -- src/strings/es.json | 2 -- src/strings/fr.json | 2 -- src/strings/he.json | 1 - src/strings/hr.json | 2 -- src/strings/hu.json | 2 -- src/strings/it.json | 2 -- src/strings/kk.json | 2 -- src/strings/ko.json | 2 -- src/strings/lt-lt.json | 1 - src/strings/nb.json | 2 -- src/strings/nl.json | 2 -- src/strings/pl.json | 2 -- src/strings/pt-br.json | 2 -- src/strings/pt-pt.json | 2 -- src/strings/ro.json | 1 - src/strings/ru.json | 2 -- src/strings/sk.json | 1 - src/strings/sv.json | 2 -- src/strings/zh-cn.json | 2 -- src/strings/zh-hk.json | 2 -- src/strings/zh-tw.json | 1 - 32 files changed, 4 insertions(+), 56 deletions(-) diff --git a/src/dashboard.html b/src/dashboard.html index 90ee2580f2..ba973280ef 100644 --- a/src/dashboard.html +++ b/src/dashboard.html @@ -95,7 +95,7 @@
-
${LabelTranscodingTemporaryFiles}
+
${LabelTranscodes}
diff --git a/src/encodingsettings.html b/src/encodingsettings.html index ae0cd83cf6..625088f569 100644 --- a/src/encodingsettings.html +++ b/src/encodingsettings.html @@ -105,7 +105,7 @@
- +
diff --git a/src/strings/ar.json b/src/strings/ar.json index 1473ae5915..4ca4e37709 100644 --- a/src/strings/ar.json +++ b/src/strings/ar.json @@ -551,9 +551,7 @@ "LabelTimeLimitHours": "الوقت المحدد (بالساعة):", "LabelTranscodingAudioCodec": "كودك تشفير الصوت:", "LabelTranscodingContainer": "الحاوية:", - "LabelTranscodingTempPath": "المسار المؤقت للتشفير البيني:", "LabelTranscodingTempPathHelp": "هذا المجلد يحتوي على ملفات قيد الاستعمال من قبل المشفر البيني. حدد مساراً مخصوصاً او اتركه فارغاً لاستعمال القيمة الافتراضية في مجلد بيانات الخادم.", - "LabelTranscodingTemporaryFiles": "الملفات المؤقتة للتشفير البيني:", "LabelTranscodingThreadCount": "عدد مسارات التشفير البيني", "LabelTranscodingThreadCountHelp": "إختر الحد الأقصى المسموح به من مسارات التشفير البيني. إن تقليل عدد المسارات سيقلل من نسبة استخدام المعالج لكنه قد لا يحوّل الوسيطة بالسرعة المطلوبة لتشغيل سلس.", "LabelTranscodingVideoCodec": "كودك تشفير الفيديو:", diff --git a/src/strings/bg-bg.json b/src/strings/bg-bg.json index be91a323e2..583a0bdb36 100644 --- a/src/strings/bg-bg.json +++ b/src/strings/bg-bg.json @@ -463,7 +463,6 @@ "LabelTimeLimitHours": "Времево ограничение (часове):", "LabelTitle": "Заглавие:", "LabelTranscodingAudioCodec": "Звуков кодек:", - "LabelTranscodingTempPath": "Временен път на прекодиране:", "LabelTranscodingTempPathHelp": "Тази папка съдържа работни файлове използвани от транскодера. Задайте място по избор или оставете празно за мястото по подразбиране.", "LabelTranscodingVideoCodec": "Видеокодек:", "LabelTriggerType": "Тип на спусъка:", diff --git a/src/strings/ca.json b/src/strings/ca.json index 0da5ac93bc..4b80ce8531 100644 --- a/src/strings/ca.json +++ b/src/strings/ca.json @@ -447,9 +447,7 @@ "LabelTrackNumber": "Pista:", "LabelTranscodingAudioCodec": "Còdec d'àudio", "LabelTranscodingContainer": "Contenidor:", - "LabelTranscodingTempPath": "Directori temporal de transcodificació:", "LabelTranscodingTempPathHelp": "Aquest directori conté fitxers emprats pel transcodificador. Especifica un directori personalitzat o deixa-ho en blanc per emprar el per defecte dins el directori de dades del servidor.", - "LabelTranscodingTemporaryFiles": "Fitxers temporals de transcodificació:", "LabelTranscodingVideoCodec": "Còdec de vídeo:", "LabelTriggerType": "Tipus de Disparador:", "LabelType": "Tipus:", diff --git a/src/strings/cs.json b/src/strings/cs.json index 7fc1dc677f..a16879447b 100644 --- a/src/strings/cs.json +++ b/src/strings/cs.json @@ -715,9 +715,7 @@ "LabelTrackNumber": "Číslo stopy:", "LabelTranscodingAudioCodec": "Audio kodek:", "LabelTranscodingContainer": "Obal:", - "LabelTranscodingTempPath": "Adresář překódování:", "LabelTranscodingTempPathHelp": "Tato složka obsahuje soubory potřebné pro překódování videí. Zadejte vlastní cestu, nebo ponechte prázdné pro použití výchozí datové složky serveru.", - "LabelTranscodingTemporaryFiles": "Dočasné soubory překódování:", "LabelTranscodingThreadCount": "Počet vláken pro překódování:", "LabelTranscodingThreadCountHelp": "Zadejte maximální počet vláken pro překódování. Snížením počtu vláken se sníží využití procesoru, ale převod nemusí být dostatečně rychlý pro plynulé přehrávání.", "LabelTranscodingVideoCodec": "Video kodek:", diff --git a/src/strings/da.json b/src/strings/da.json index 12dff74d51..9bbda656ea 100644 --- a/src/strings/da.json +++ b/src/strings/da.json @@ -662,9 +662,7 @@ "LabelTitle": "Titel:", "LabelTrackNumber": "Spor nummer:", "LabelTranscodingAudioCodec": "Lyd codec:", - "LabelTranscodingTempPath": "Midlertidig sti til transkodning:", "LabelTranscodingTempPathHelp": "Denne mappe indeholder transkoderens arbejdsfiler. Definer en alternativ sti eller lad den stå tom for at bruge standardmappen i serverens datamappe.", - "LabelTranscodingTemporaryFiles": "Midlertidige filer for transkodning:", "LabelTranscodingThreadCount": "Antal af omkodningstråde:", "LabelTranscodingThreadCountHelp": "Vælg det maksimale antal af tråde der bruges under omkodning. Reduktion af antallet af tråde sænker cpu-forbrug, men resulterer muligvis i at konverteringer ikke foregår hurtigt nok til en jævn afspilning.", "LabelTriggerType": "Udløsertype:", diff --git a/src/strings/de.json b/src/strings/de.json index a34911a35f..6c93871eb4 100644 --- a/src/strings/de.json +++ b/src/strings/de.json @@ -784,9 +784,7 @@ "LabelTitle": "Titel:", "LabelTrackNumber": "Stück Nummer:", "LabelTranscodingAudioCodec": "Audio Codec:", - "LabelTranscodingTempPath": "Temporärer Transcoding Pfad:", "LabelTranscodingTempPathHelp": "Dieses Verzeichnis beinhaltet Dateien die für den Betrieb des Transcoders benutzt werden. Wähle einen eigenen Pfad oder lasse das Feld frei, um den Standardspeicherort im Server Datenverzeichnis zu nutzen.", - "LabelTranscodingTemporaryFiles": "Temporäre Transkodierdateien:", "LabelTranscodingThreadCount": "Anzahl Transkodierungs-Threads:", "LabelTranscodingThreadCountHelp": "Legen Sie die maximale Anzahl von Transkodierungs-Threads fest. Das Reduzieren der Thread-Anzahl verringert die CPU Auslastung, wird aber möglicherweise die Transkodierung nicht schnell genug für eine störungsfrei Wiedergabe ermöglichen.", "LabelTranscodingVideoCodec": "Video Codec:", diff --git a/src/strings/el.json b/src/strings/el.json index 94e904ed9a..325ab2fbc7 100644 --- a/src/strings/el.json +++ b/src/strings/el.json @@ -700,9 +700,7 @@ "LabelTimeLimitHours": "Όριο χρόνου (ώρες):", "LabelTitle": "Τίτλος:", "LabelTrackNumber": "Αριθμός Κομματιού:", - "LabelTranscodingTempPath": "Προσωρινός φάκελος Κωδικοποίησης ", "LabelTranscodingTempPathHelp": "Αυτός ο φάκελος περιέχει αρχεία εργασίας που χρησιμοποιούνται από τον μετασχηματιστή. Καθορίστε μια προσαρμοσμένη διαδρομή ή αφήστε κενό για να χρησιμοποιήσετε την προεπιλογή στο φάκελο δεδομένων του διακομιστή.", - "LabelTranscodingTemporaryFiles": "Προσωρινός φάκελος Κωδικοποίησης ", "LabelTranscodingThreadCountHelp": "Επιλέξτε τον μέγιστο αριθμό θεμάτων που θα χρησιμοποιήσετε κατά την αναδιαμόρφωση. Η μείωση του αριθμού των νημάτων θα μειώσει τη χρήση του επεξεργαστή, αλλά δεν μπορεί να μετατρέψει αρκετά γρήγορα για μια ομαλή αναπαραγωγή.", "LabelTriggerType": "Τύπος διακόπτη", "LabelTunerIpAddress": "Διεύθυνση IP του δέκτη:", diff --git a/src/strings/en-us.json b/src/strings/en-us.json index eda4b8805b..2a3e7d526e 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -842,9 +842,9 @@ "LabelTrackNumber": "Track number:", "LabelTranscodingAudioCodec": "Audio codec:", "LabelTranscodingContainer": "Container:", - "LabelTranscodingTempPath": "Transcoding temporary path:", + "LabelTranscodePath": "Transcode path:", "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", - "LabelTranscodingTemporaryFiles": "Transcoding temporary files:", + "LabelTranscodes": "Transcodes:", "LabelTranscodingThreadCount": "Transcoding thread count:", "LabelTranscodingThreadCountHelp": "Select the maximum number of threads to use when transcoding. Reducing the thread count will lower cpu usage but may not convert fast enough for a smooth playback experience.", "LabelTranscodingVideoCodec": "Video codec:", diff --git a/src/strings/es-mx.json b/src/strings/es-mx.json index 03c534f4e3..445ba02c6e 100644 --- a/src/strings/es-mx.json +++ b/src/strings/es-mx.json @@ -821,9 +821,7 @@ "LabelTrackNumber": "Número de Pista:", "LabelTranscodingAudioCodec": "Codec de audio:", "LabelTranscodingContainer": "Contenedor:", - "LabelTranscodingTempPath": "Ruta para transcodificación temporal:", "LabelTranscodingTempPathHelp": "Esta carpeta contiene archivos de trabajo usados por el transcodificador. Especifique una ruta personalizada, o déjela vacía para utilizar su valor por omisión en la carpeta de datos del servidor.", - "LabelTranscodingTemporaryFiles": "Archivos temporales de transcodificación:", "LabelTranscodingThreadCount": "Conteo de hilos de transcodificación:", "LabelTranscodingThreadCountHelp": "Elija el numero máximo de hilos a usar para transcodificar. Reduciendo el conteo de hilos disminuirá el uso del cpu pero es posible que no convierta lo suficientemente rápido para obtener una reproducción fluida.", "LabelTranscodingVideoCodec": "Codec de video:", diff --git a/src/strings/es.json b/src/strings/es.json index 0922ecaa42..9130571eed 100644 --- a/src/strings/es.json +++ b/src/strings/es.json @@ -749,9 +749,7 @@ "LabelTrackNumber": "Número de pista:", "LabelTranscodingAudioCodec": "Codec de audio:", "LabelTranscodingContainer": "Contenedor:", - "LabelTranscodingTempPath": "Ruta temporal de transcodificación:", "LabelTranscodingTempPathHelp": "Esta carpeta contiene achivos en uso por el transcodificador. Especificar una ruta personalizada, o dejarla vacía para usar la ruta predeterminada en la carpeta de datos del servidor.", - "LabelTranscodingTemporaryFiles": "Archivos temporales de transcodificación:", "LabelTranscodingThreadCount": "Cantidad de instancias de transcodificación:", "LabelTranscodingThreadCountHelp": "Selecciona el número máximo de instancias de transcodificación. Reducirlas disminuirá la carga del procesador pero no convertirá lo suficientemente rápido para una reproducción fluida.", "LabelTranscodingVideoCodec": "Codec de video:", diff --git a/src/strings/fr.json b/src/strings/fr.json index 08fdc280d1..171837cceb 100644 --- a/src/strings/fr.json +++ b/src/strings/fr.json @@ -820,9 +820,7 @@ "LabelTrackNumber": "Numéro de piste :", "LabelTranscodingAudioCodec": "Codec audio :", "LabelTranscodingContainer": "Conteneur :", - "LabelTranscodingTempPath": "Chemin d'accès du répertoire temporaire de transcodage :", "LabelTranscodingTempPathHelp": "Ce dossier contient les fichiers temporaires utilisés par le transcodeur. Spécifiez un chemin personnalisé ou laissez vide pour utiliser le chemin par défaut dans le dossier de données du serveur.", - "LabelTranscodingTemporaryFiles": "Fichiers temporaires de transcodage :", "LabelTranscodingThreadCount": "Nombre de threads de transcodage :", "LabelTranscodingThreadCountHelp": "Sélectionnez le nombre maximum de threads à utiliser pour le transcodage. La réduction de cette valeur réduira l'utilisation du processeur mais pourrait ne pas suffire pour maintenir une lecture fluide.", "LabelTranscodingVideoCodec": "Codec vidéo :", diff --git a/src/strings/he.json b/src/strings/he.json index 9487fc63f7..600c9ab7de 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -268,7 +268,6 @@ "LabelTimeLimitHours": "הגבלת זמן (בשעות)", "LabelTitle": "כותרת:", "LabelTrackNumber": "קטע מספר:", - "LabelTranscodingTempPath": "נתיב לקידוד זמני:", "LabelTriggerType": "סוגר טריגר:", "LabelType": "סוג:", "LabelUseNotificationServices": "השתמש בשירותים הבאים:", diff --git a/src/strings/hr.json b/src/strings/hr.json index f7b64f7048..7fa4a990f1 100644 --- a/src/strings/hr.json +++ b/src/strings/hr.json @@ -597,9 +597,7 @@ "LabelTrackNumber": "Broj pjesme:", "LabelTranscodingAudioCodec": "Audio koder:", "LabelTranscodingContainer": "Spremnik:", - "LabelTranscodingTempPath": "Privremena putanja konvertiranja:", "LabelTranscodingTempPathHelp": "Ova mapa sadrži radne datoteke koje koristi konverter. Navedite prilagođenu putanju ili ostavite prazno za korištenje zadanog unutar mape podataka poslužitelja.", - "LabelTranscodingTemporaryFiles": "Privremene datoteke konvertiranja:", "LabelTranscodingThreadCount": "Broj niti konvertiranja:", "LabelTranscodingThreadCountHelp": "Odaberite maksimalan broj niti koje će se koristiti kada se konvertira. Manji broj niti će smanjiti upotrebu procesora, ali moguće da neće konvertirati dovoljno brzo za glatke reprodukcije.", "LabelTranscodingVideoCodec": "Video koder:", diff --git a/src/strings/hu.json b/src/strings/hu.json index abf0c730f0..ac181eee61 100644 --- a/src/strings/hu.json +++ b/src/strings/hu.json @@ -1018,9 +1018,7 @@ "LabelTextBackgroundColor": "Szöveg háttérszín:", "LabelTextColor": "Szöveg szín:", "LabelTextSize": "Szövegméret:", - "LabelTranscodingTempPath": "Átkódolás ideiglenes útvonala:", "LabelTranscodingTempPathHelp": "Ez a mappa az átkódoló által használt munkafájlokat tartalmazza. Adj meg egyéni útvonalat, vagy hagyd üresen a szerver alapértelmezetten beálíltásához.", - "LabelTranscodingTemporaryFiles": "Átkódolás ideiglenes fájljai:", "LabelTranscodingThreadCount": "Átkódolási CPU szálak száma:", "LabelTranscodingThreadCountHelp": "Válaszd ki az átkódolás során használni kívánt szálak maximális számát. A szálszám csökkentése csökkenti a processzor használatát, de lehet nem lesz képes elég gyorsan átalakítani a folyamatos lejátszási élményhez.", "LabelTunerIpAddress": "Tuner IP címe:", diff --git a/src/strings/it.json b/src/strings/it.json index 7aa1abb88c..ec77416273 100644 --- a/src/strings/it.json +++ b/src/strings/it.json @@ -792,9 +792,7 @@ "LabelTrackNumber": "Numero traccia:", "LabelTranscodingAudioCodec": "Codec Audio:", "LabelTranscodingContainer": "contenitore:", - "LabelTranscodingTempPath": "Cartella temporanea per la trascodifica:", "LabelTranscodingTempPathHelp": "Questa cartella contiene i file di lavoro utilizzati dal transcoder. Specificare un percorso personalizzato, oppure lasciare vuoto per utilizzare l'impostazione predefinita all'interno della cartella dei dati del server.", - "LabelTranscodingTemporaryFiles": "Transcodifica file temporanei:", "LabelTranscodingThreadCount": "Transcodifica numero di thread:", "LabelTranscodingThreadCountHelp": "Selezionare il numero massimo di thread da utilizzare durante la transcodifica. Ridurre il numero di thread si abbasserà l'utilizzo della CPU, ma non può convertire abbastanza veloce per un'esperienza di riproduzione fluida.", "LabelTranscodingVideoCodec": "Codec Video:", diff --git a/src/strings/kk.json b/src/strings/kk.json index ddef0bf5a7..6e19e43eb9 100644 --- a/src/strings/kk.json +++ b/src/strings/kk.json @@ -836,9 +836,7 @@ "LabelTrackNumber": "Jolshyq nómiri:", "LabelTranscodingAudioCodec": "Dybystyq kodek:", "LabelTranscodingContainer": "Konteıner:", - "LabelTranscodingTempPath": "Transcoding temporary qaltasynyń joly:", "LabelTranscodingTempPathHelp": "Bul qalta quramynda qaıta kodtaý quraly paıdalanatyn jumys faıldary bar. Teńshelgen joldy anyqtańyz, nemese serverdiń derekter qaltasy ishindegi ádepkisin paıdalaný úshin bos qaldyryńyz.", - "LabelTranscodingTemporaryFiles": "Qaıta kodtaýynyń ýaqytsha faıldary:", "LabelTranscodingThreadCount": "Qaıta qodtaý tizbekterdiń sany:", "LabelTranscodingThreadCountHelp": "Qaıta kodtaý kezinde paıdalanatyn eń kóp tizbek sanyn tańdańyz. Tizbek sanyn azaıtý OP paıdalanýyn tómendetedi, biraq jatyq oınatý áseri úshin tez túrlendirýge jetkilikti bolmaýy múmkin.", "LabelTranscodingVideoCodec": "Beınelik kodek:", diff --git a/src/strings/ko.json b/src/strings/ko.json index dcc386abbd..530277bb85 100644 --- a/src/strings/ko.json +++ b/src/strings/ko.json @@ -468,9 +468,7 @@ "LabelTrackNumber": "트랙 번호:", "LabelTranscodingAudioCodec": "오디오 코덱:", "LabelTranscodingContainer": "컨테이너:", - "LabelTranscodingTempPath": "임시 트랜스코딩 경로:", "LabelTranscodingTempPathHelp": "트랜스코더가 사용하는 작업 파일을 보관하는 폴더입니다. 사용자 경로를 지정하거나 서버의 데이터 폴더를 기본으로 사용하려면 비워둡니다.", - "LabelTranscodingTemporaryFiles": "트랜스코딩 임시 파일:", "LabelTranscodingVideoCodec": "비디오 코덱:", "LabelTriggerType": "트리거 종류:", "LabelTunerIpAddress": "튜너 IP 주소", diff --git a/src/strings/lt-lt.json b/src/strings/lt-lt.json index a9ce1629a3..cbaa4ef77d 100644 --- a/src/strings/lt-lt.json +++ b/src/strings/lt-lt.json @@ -292,7 +292,6 @@ "LabelTimeLimitHours": "Laiko limitas (val.):", "LabelTitle": "Pavadinimas:", "LabelTrackNumber": "Dainos numeris:", - "LabelTranscodingTempPath": "Transkodavimo laikinas kelias:", "LabelTranscodingTempPathHelp": "Šiame aplanke bus darbiniai transkoderio failai. Nurodykite savo vietą, arba palikite tuščią, kad būtų naudojamas serverio duomenų aplankas.", "LabelTriggerType": "Jungiklio tipas:", "LabelType": "Tipas:", diff --git a/src/strings/nb.json b/src/strings/nb.json index c2b55a9382..e0bdcaaa07 100644 --- a/src/strings/nb.json +++ b/src/strings/nb.json @@ -663,9 +663,7 @@ "LabelTrackNumber": "Spor nummer:", "LabelTranscodingAudioCodec": "lyd kodek:", "LabelTranscodingContainer": "Kontainer:", - "LabelTranscodingTempPath": "Sti for midlertidig transcoding:", "LabelTranscodingTempPathHelp": "Denne mappen inneholder fungerende filer som blir brukt av transcoderen. Spesifiser en tilpasset sti eller la det stå tomt for å benytte serverens standard sti.", - "LabelTranscodingTemporaryFiles": "Transcoder midlertidige filer:", "LabelTranscodingThreadCount": "Antall tråder for transkoding", "LabelTranscodingThreadCountHelp": "Velg maksimalt antall tråder som skal brukes når transkoding. Redusering av tråder vil senke CPU-bruk, men kan resultere i at Jellyfin ikke konvertere raskt nok for en jevn avspillingsopplevelse.", "LabelTranscodingVideoCodec": "Video kodek:", diff --git a/src/strings/nl.json b/src/strings/nl.json index 8057cf2ead..f6b8e45970 100644 --- a/src/strings/nl.json +++ b/src/strings/nl.json @@ -784,9 +784,7 @@ "LabelTitle": "Titel:", "LabelTrackNumber": "Tracknummer:", "LabelTranscodingAudioCodec": "Geluidscodec:", - "LabelTranscodingTempPath": "Tijdelijk transcodeer pad:", "LabelTranscodingTempPathHelp": "Deze map bevat werkbestanden die worden gebruikt door de transcoder. Geef een eigen locatie op of laat het leeg om de standaardlocatie te gebruiken.", - "LabelTranscodingTemporaryFiles": "Tijdelijke transcodeer bestanden:", "LabelTranscodingThreadCount": "Aantal transcodeer threads:", "LabelTranscodingThreadCountHelp": "Selecteer het maximale aantal threads die gebruikt mogen worden om te transcoderen. Bij een lager aantal zal het CPU gebruik lager zijn, maar kan de afspeelkwaliteit minder zijn.", "LabelTunerIpAddress": "Tuner IP adres:", diff --git a/src/strings/pl.json b/src/strings/pl.json index dae806aa6b..7e41d6ca9f 100644 --- a/src/strings/pl.json +++ b/src/strings/pl.json @@ -833,9 +833,7 @@ "LabelTrackNumber": "Numer utworu:", "LabelTranscodingAudioCodec": "Kodek audio:", "LabelTranscodingContainer": "Kontener:", - "LabelTranscodingTempPath": "Folder tymczasowy transkodowania:", "LabelTranscodingTempPathHelp": "Folder ten zawiera pliki używane przez silnik transkodowania. Wprowadź niestandardowy folder lub zostaw puste, aby używać domyślnego folderu danych serwera.", - "LabelTranscodingTemporaryFiles": "Tymczasowe pliki transkodowania:", "LabelTranscodingThreadCount": "Liczba wątków transkodowania:", "LabelTranscodingThreadCountHelp": "Wybierz maksymalną liczbę wątków dla transkodowania. Ograniczenie ich liczby, obniży poziom użycia procesora, ale może niekorzystnie wpłynąć na płynność odtwarzania.", "LabelTranscodingVideoCodec": "Kodek wideo:", diff --git a/src/strings/pt-br.json b/src/strings/pt-br.json index a13ff50254..68aba833cb 100644 --- a/src/strings/pt-br.json +++ b/src/strings/pt-br.json @@ -811,9 +811,7 @@ "LabelTitle": "Título:", "LabelTrackNumber": "Número da faixa:", "LabelTranscodingAudioCodec": "Codec do Áudio:", - "LabelTranscodingTempPath": "Local temporário para transcodificação:", "LabelTranscodingTempPathHelp": "Esta pasta contém arquivos ativos usados pelo transcodificador. Especifique um local personalizado ou deixe em branco para usar o padrão dentro da pasta de dados do servidor.", - "LabelTranscodingTemporaryFiles": "Arquivos temporários da transcodificação:", "LabelTranscodingThreadCount": "Contagem de threads da transcodificação:", "LabelTranscodingThreadCountHelp": "Selecione o número máximo de threads a ser usado quando transcodificar. Reduzir o número de threads irá diminuir o uso da CPU, mas pode não converter rápido o suficiente para uma experiência de reprodução suave.", "LabelTranscodingVideoCodec": "Codec do vídeo:", diff --git a/src/strings/pt-pt.json b/src/strings/pt-pt.json index 87dadc3f12..b45874af3e 100644 --- a/src/strings/pt-pt.json +++ b/src/strings/pt-pt.json @@ -490,9 +490,7 @@ "LabelTimeLimitHours": "Limite de tempo (horas):", "LabelTranscodingAudioCodec": "Codec do Áudio:", "LabelTranscodingContainer": "Contentor:", - "LabelTranscodingTempPath": "Localização temporária das transcodificações:", "LabelTranscodingTempPathHelp": "Esta pasta contém arquivos ativos usados pelo transcodificador. Especifique um local personalizado ou deixe em branco para usar o padrão dentro da pasta de dados do servidor.", - "LabelTranscodingTemporaryFiles": "Ficheiros temporários da transcodificação:", "LabelTranscodingThreadCount": "Contagem de threads da transcodificação:", "LabelTranscodingThreadCountHelp": "Selecione o número máximo de threads a ser usado quando transcodificar. Reduzir o número de threads irá diminuir o uso da CPU, mas pode não converter rápido o suficiente para uma experiência de reprodução suave.", "LabelTranscodingVideoCodec": "Codec do vídeo:", diff --git a/src/strings/ro.json b/src/strings/ro.json index 0d14f0eb72..96f31ffad8 100644 --- a/src/strings/ro.json +++ b/src/strings/ro.json @@ -107,7 +107,6 @@ "LabelSeriesRecordingPath": "Calea pentru înregistrări seriale (opțional):", "LabelStopWhenPossible": "Oprește când este posibil:", "LabelTimeLimitHours": "Limită de timp(ore):", - "LabelTranscodingTempPath": "Cale temporară pentru conversie:", "LabelTranscodingTempPathHelp": "Acest director conține fișierele de lucru folosite de convertor. Specificați o cale specială sau lasați gol pentru a folosi pe cea implicită în directorul de lucru al serverului.", "LabelTriggerType": "Tip Declanșator:", "LabelUser": "Utilizator:", diff --git a/src/strings/ru.json b/src/strings/ru.json index 3dbcf92fec..673942bc09 100644 --- a/src/strings/ru.json +++ b/src/strings/ru.json @@ -836,9 +836,7 @@ "LabelTrackNumber": "Номер дорожки:", "LabelTranscodingAudioCodec": "Аудио профиль:", "LabelTranscodingContainer": "Контейнер:", - "LabelTranscodingTempPath": "Путь ко временным файлам перекодировки:", "LabelTranscodingTempPathHelp": "В данной папке содержатся рабочие файлы, используемые при перекодировке. Укажите произвольный путь, или не заполняйте, чтобы использовать стандартный в пределах серверной папки data.", - "LabelTranscodingTemporaryFiles": "Временные файлы перекодировки:", "LabelTranscodingThreadCount": "Количество перекодирующих подпотоков:", "LabelTranscodingThreadCountHelp": "Выберите максимальное число подпотоков для использования при перекодировке. Сокращение числа подпотоков понижает нагрузку на ЦП, но преобразование может оказаться недостаточно быстрым для впечатления плавного воспроизведения.", "LabelTranscodingVideoCodec": "Видео кодек:", diff --git a/src/strings/sk.json b/src/strings/sk.json index a7580efb23..5346226994 100644 --- a/src/strings/sk.json +++ b/src/strings/sk.json @@ -504,7 +504,6 @@ "LabelTrackNumber": "Číslo stopy:", "LabelTranscodingAudioCodec": "Audio kodek:", "LabelTranscodingContainer": "Obal:", - "LabelTranscodingTempPath": "Dočasné umiestnenie transkódovania:", "LabelTranscodingVideoCodec": "Video kodek:", "LabelTunerIpAddress": "IP adresa tunera:", "LabelTunerType": "Typ tunera:", diff --git a/src/strings/sv.json b/src/strings/sv.json index c31b60e354..58d8ffed18 100644 --- a/src/strings/sv.json +++ b/src/strings/sv.json @@ -781,9 +781,7 @@ "LabelTrackNumber": "Spår nr", "LabelTranscodingAudioCodec": "Ljudkodning:", "LabelTranscodingContainer": "Behållare:", - "LabelTranscodingTempPath": "Mellanlagringsplats för omkodning:", "LabelTranscodingTempPathHelp": "Denna mapp innehåller tillfälliga filer som används vid omkodning. Ange en plats för dessa, eller lämna blankt för att använda förvald plats.", - "LabelTranscodingTemporaryFiles": "Tillfälliga omkodningsfiler:", "LabelTranscodingThreadCount": "Trådar för omkodning:", "LabelTranscodingThreadCountHelp": "Välj maximala antalet trådar som ska användas vid omkodning. Att minska antalet trådar sänker cpu-belastningan men ökar även risken att omkodning inte kan ske snabbt nog för felfri uppspelning.", "LabelTranscodingVideoCodec": "Videokodning:", diff --git a/src/strings/zh-cn.json b/src/strings/zh-cn.json index a616f48e27..362e9cf39c 100644 --- a/src/strings/zh-cn.json +++ b/src/strings/zh-cn.json @@ -792,9 +792,7 @@ "LabelTrackNumber": "音轨号码:", "LabelTranscodingAudioCodec": "音频编解码器:", "LabelTranscodingContainer": "媒体载体", - "LabelTranscodingTempPath": "临时解码路径:", "LabelTranscodingTempPathHelp": "此文件夹包含用于转码的工作文件。请自定义路径,或留空以使用默认的服务器数据文件夹。", - "LabelTranscodingTemporaryFiles": "用于转码的临时文件夹:", "LabelTranscodingThreadCount": "转码线程数:", "LabelTranscodingThreadCountHelp": "选择转码时使用的最大线程数。\n减少线程数量将会降低CPU使用率,可能无法快速进行转换并流畅的播放。", "LabelTranscodingVideoCodec": "视频编解码器:", diff --git a/src/strings/zh-hk.json b/src/strings/zh-hk.json index d48664d513..6c5dcad1b8 100644 --- a/src/strings/zh-hk.json +++ b/src/strings/zh-hk.json @@ -177,9 +177,7 @@ "LabelStatus": "狀態:", "LabelTime": "時間:", "LabelTimeLimitHours": "時限(小時):", - "LabelTranscodingTempPath": "臨時轉碼路徑:", "LabelTranscodingTempPathHelp": "此文件夾包含轉換器需要的文件。選擇自定路徑,保留空白以使用默認伺服器的數據文件夾。", - "LabelTranscodingTemporaryFiles": "暫存轉碼文件:", "LabelTriggerType": "觸發類型:", "LabelUser": "用戶:", "LabelVersionInstalled": "已安裝 {0}", diff --git a/src/strings/zh-tw.json b/src/strings/zh-tw.json index 75bb58e41b..b64987efe2 100644 --- a/src/strings/zh-tw.json +++ b/src/strings/zh-tw.json @@ -144,7 +144,6 @@ "LabelSaveLocalMetadata": "將媒體圖像及資料檔存到媒體所在的資料夾", "LabelSaveLocalMetadataHelp": "直接保存媒體圖像及資料到媒體所在的文件夾能使編輯工作更容易。", "LabelTime": "時間:", - "LabelTranscodingTempPath": "轉碼臨時路徑:", "LabelTriggerType": "觸發類型:", "LabelUser": "使用者:", "LabelYourFirstName": "你的名字:", From 0fe1d350e6b15170086a3269530a37b7f4bacf27 Mon Sep 17 00:00:00 2001 From: Phallacy Date: Mon, 25 Mar 2019 00:30:45 -0700 Subject: [PATCH 158/220] removes useless connectlinktype check --- src/scripts/useredit.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/scripts/useredit.js b/src/scripts/useredit.js index e972627c88..7c355078c0 100644 --- a/src/scripts/useredit.js +++ b/src/scripts/useredit.js @@ -36,13 +36,8 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, l } else { $(".disabledUserBanner", page).hide(); } - if ("Guest" == user.ConnectLinkType) { - $("#fldConnectInfo", page).hide(); - $("#txtUserName", page).prop("disabled", "disabled"); - } else { - $("#txtUserName", page).prop("disabled", "").removeAttr("disabled"); - $("#fldConnectInfo", page).show(); - } + $("#txtUserName", page).prop("disabled", "").removeAttr("disabled"); + $("#fldConnectInfo", page).show(); $(".lnkEditUserPreferences", page).attr("href", "mypreferencesmenu.html?userId=" + user.Id); libraryMenu.setTitle(user.Name); page.querySelector(".username").innerHTML = user.Name; From 518ed623e2f38fe37f30f33f24cf02d565171a15 Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 25 Mar 2019 15:18:13 -0700 Subject: [PATCH 159/220] fix eslint ci error --- src/components/appRouter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/appRouter.js b/src/components/appRouter.js index dc959faa46..92950c66f6 100644 --- a/src/components/appRouter.js +++ b/src/components/appRouter.js @@ -101,7 +101,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM }; if (route.controller) { - require([`controllers/${route.controller}`], onInitComplete); + require(['controllers/' + route.controller], onInitComplete); } else { onInitComplete(); } From 24ed198960dcbcaf1789fd4c5553c5d5635ed8a4 Mon Sep 17 00:00:00 2001 From: Phallacy Date: Mon, 25 Mar 2019 22:41:16 -0700 Subject: [PATCH 160/220] adds strings and a link on the password reset page --- src/controllers/forgotpassword.js | 2 +- src/strings/en-us.json | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/controllers/forgotpassword.js b/src/controllers/forgotpassword.js index fc944a410a..f31c5724a7 100644 --- a/src/controllers/forgotpassword.js +++ b/src/controllers/forgotpassword.js @@ -12,7 +12,7 @@ define([], function() { }); if ("PinCode" == result.Action) { var msg = Globalize.translate("MessageForgotPasswordFileCreated"); - return msg += "
", msg += "
", msg += result.PinFile, msg += "
", void Dashboard.alert({ + return msg += "
", msg += "
", msg += "Enter PIN here to finish Password Reset" ,msg += "
",msg += result.PinFile, msg += "
", void Dashboard.alert({ message: msg, title: Globalize.translate("HeaderForgotPassword") }) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 765e74cf86..cdaba76e06 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -40,6 +40,7 @@ "AspectRatio": "Aspect ratio", "AttributeNew": "New", "Audio": "Audio", + "AuthProviderHelp": "Select an Authentication Provider to be used to Authenticate this user's password", "Auto": "Auto", "AutoBasedOnLanguageSetting": "Auto (based on language setting)", "Backdrop": "Backdrop", @@ -548,6 +549,7 @@ "LabelArtistsHelp": "Separate multiple using ;", "LabelAudio": "Audio:", "LabelAudioLanguagePreference": "Preferred audio language:", + "LabelAuthProvider": "Authentication Provider:", "LabelAutomaticallyRefreshInternetMetadataEvery": "Automatically refresh metadata from the internet:", "LabelBindToLocalNetworkAddress": "Bind to local network address:", "LabelBindToLocalNetworkAddressHelp": "Optional. Override the local IP address to bind the http server to. If left empty, the server will bind to all availabile addresses. Changing this value requires restarting Jellyfin Server.", @@ -746,6 +748,7 @@ "LabelParentalRating": "Parental rating:", "LabelPassword": "Password:", "LabelPasswordConfirm": "Password (confirm):", + "LabelPasswordResetProvider": "Password Reset Provider:", "LabelPasswordRecoveryPinCode": "Pin code:", "LabelPath": "Path:", "LabelPersonRole": "Role:", @@ -961,7 +964,7 @@ "MessageNoServersAvailableToConnect": "No servers are available to connect to. If you've been invited to share a server, make sure to accept it below or by clicking the link in the email.", "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "MessageNothingHere": "Nothing here.", - "MessagePasswordResetForUsers": "Passwords have been removed for the following users. To login, sign in with a blank password.", + "MessagePasswordResetForUsers": "The following users have had their passwords reset. They can now sign in with the PIN code that was used this reset.", "MessagePlayAccessRestricted": "Playback of this content is currently restricted. Please contact your Jellyfin Server administrator for more information.", "MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.", "MessagePleaseWait": "Please wait. This may take a minute.", @@ -1170,6 +1173,7 @@ "PasswordResetComplete": "The password has been reset.", "PasswordResetConfirmation": "Are you sure you wish to reset the password?", "PasswordResetHeader": "Reset Password", + "PasswordResetProviderHelp": "Choose a Password Reset Provider to be used if this user resets their password", "PasswordSaved": "Password saved.", "People": "People", "PerfectMatch": "Perfect match", From 82e0a2f7da8f17590c4fbac12acbba3bf0c03a85 Mon Sep 17 00:00:00 2001 From: Phallacy Date: Mon, 25 Mar 2019 22:43:32 -0700 Subject: [PATCH 161/220] replaces a duplicate anthonylavado with me --- CONTRIBUTORS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 9a343ddd15..bbdb64f7a5 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -19,7 +19,7 @@ - [nkmerrill](https://github.com/nkmerrill) - [TtheCreator](https://github.com/Tthecreator) - [RazeLighter777](https://github.com/RazeLighter777) - - [anthonylavado](https://github.com/anthonylavado) + - [LogicalPhallacy](https://github.com/LogicalPhallacy) # Emby Contributors From 521f09f79fc8980089bb47221737223c52550125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorben=20Br=C3=A4utigam?= Date: Wed, 27 Mar 2019 15:38:37 +0100 Subject: [PATCH 162/220] Fix Issue #213 --- src/components/filesystem.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/filesystem.js b/src/components/filesystem.js index e022a1c6d0..3ab759b28a 100644 --- a/src/components/filesystem.js +++ b/src/components/filesystem.js @@ -6,11 +6,13 @@ define([], function () { if (window.NativeShell && window.NativeShell.FileSystem) { return window.NativeShell.FileSystem.fileExists(path); } + return Promise.reject(); }, directoryExists: function (path) { if (window.NativeShell && window.NativeShell.FileSystem) { return window.NativeShell.FileSystem.directoryExists(path); } + return Promise.reject(); } }; }); \ No newline at end of file From e01feca025798f518f4c5acb00bb680a489d8c03 Mon Sep 17 00:00:00 2001 From: Vasily Date: Wed, 27 Mar 2019 10:02:48 -0700 Subject: [PATCH 163/220] Deuglify Co-Authored-By: LogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com> --- src/scripts/useredit.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/scripts/useredit.js b/src/scripts/useredit.js index 96003fb74d..853bb2454d 100644 --- a/src/scripts/useredit.js +++ b/src/scripts/useredit.js @@ -22,7 +22,11 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, l } function loadPasswordResetProviders(page, user, providers) { - providers.length > 1 && !user.Policy.IsAdministrator ? page.querySelector(".fldSelectPasswordResetProvider").classList.remove("hide") : page.querySelector(".fldSelectPasswordResetProvider").classList.add("hide"); + if (providers.length > 1 && !user.Policy.IsAdministrator) { + page.querySelector(".fldSelectPasswordResetProvider").classList.remove("hide"); + } else { + page.querySelector(".fldSelectPasswordResetProvider").classList.add("hide"); + } var currentProviderId = user.Policy.PasswordResetProviderId; page.querySelector(".selectPasswordResetProvider").innerHTML = providers.map(function(provider) { var selected = provider.Id === currentProviderId || providers.length < 2 ? " selected" : ""; From 6c3814f014fca6c5570521d9673fdc3d3f9c6157 Mon Sep 17 00:00:00 2001 From: Vasily Date: Wed, 27 Mar 2019 13:42:01 -0700 Subject: [PATCH 164/220] Apply suggestions from code review Co-Authored-By: LogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com> --- src/scripts/useredit.js | 2 +- src/strings/en-us.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripts/useredit.js b/src/scripts/useredit.js index 853bb2454d..356a93c4e7 100644 --- a/src/scripts/useredit.js +++ b/src/scripts/useredit.js @@ -29,7 +29,7 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, l } var currentProviderId = user.Policy.PasswordResetProviderId; page.querySelector(".selectPasswordResetProvider").innerHTML = providers.map(function(provider) { - var selected = provider.Id === currentProviderId || providers.length < 2 ? " selected" : ""; + var selected = (provider.Id === currentProviderId || providers.length < 2) ? " selected" : ""; return '" }) } diff --git a/src/strings/en-us.json b/src/strings/en-us.json index cdaba76e06..2189e827b2 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -964,7 +964,7 @@ "MessageNoServersAvailableToConnect": "No servers are available to connect to. If you've been invited to share a server, make sure to accept it below or by clicking the link in the email.", "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "MessageNothingHere": "Nothing here.", - "MessagePasswordResetForUsers": "The following users have had their passwords reset. They can now sign in with the PIN code that was used this reset.", + "MessagePasswordResetForUsers": "The following users have had their passwords reset. They can now sign in with the PIN codes that were used to perform the reset.", "MessagePlayAccessRestricted": "Playback of this content is currently restricted. Please contact your Jellyfin Server administrator for more information.", "MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.", "MessagePleaseWait": "Please wait. This may take a minute.", From 18af617c741f92a8ac448a990cc9cdccdf654e8c Mon Sep 17 00:00:00 2001 From: Phallacy Date: Wed, 27 Mar 2019 22:51:27 -0700 Subject: [PATCH 165/220] minor fixes --- src/controllers/forgotpassword.js | 2 +- src/strings/en-us.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/forgotpassword.js b/src/controllers/forgotpassword.js index f31c5724a7..bb9489a11a 100644 --- a/src/controllers/forgotpassword.js +++ b/src/controllers/forgotpassword.js @@ -12,7 +12,7 @@ define([], function() { }); if ("PinCode" == result.Action) { var msg = Globalize.translate("MessageForgotPasswordFileCreated"); - return msg += "
", msg += "
", msg += "Enter PIN here to finish Password Reset" ,msg += "
",msg += result.PinFile, msg += "
", void Dashboard.alert({ + return msg += "
", msg += "
", msg += "Enter PIN here to finish Password Reset" ,msg += "
",msg += result.PinFile, msg += "
", void Dashboard.alert({ message: msg, title: Globalize.translate("HeaderForgotPassword") }) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index cdaba76e06..38da20bc12 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -1173,7 +1173,7 @@ "PasswordResetComplete": "The password has been reset.", "PasswordResetConfirmation": "Are you sure you wish to reset the password?", "PasswordResetHeader": "Reset Password", - "PasswordResetProviderHelp": "Choose a Password Reset Provider to be used if this user resets their password", + "PasswordResetProviderHelp": "Choose a Password Reset Provider to be used when this user requests a password reset", "PasswordSaved": "Password saved.", "People": "People", "PerfectMatch": "Perfect match", From 93c5157b1e224b82b1da32602787594ea9b68914 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Tue, 26 Feb 2019 23:28:16 +0000 Subject: [PATCH 166/220] refactor and module resolution for appStorage --- src/bower_components/apiclient/appStorage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bower_components/apiclient/appStorage.js b/src/bower_components/apiclient/appStorage.js index 8be2bb4d7f..6083bb4953 100644 --- a/src/bower_components/apiclient/appStorage.js +++ b/src/bower_components/apiclient/appStorage.js @@ -30,7 +30,7 @@ define([], function() { this.getItem = function(name) { return localStorage.getItem(name); }; - + this.removeItem = function(name) { localStorage.removeItem(name); From afde8bebe710c3b724bdc224a65bddfae85f8cbc Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Wed, 27 Feb 2019 22:26:23 +0000 Subject: [PATCH 167/220] removed module emby-linkbutton: same as emby-button --- src/components/collectioneditor/collectioneditor.js | 2 +- src/components/directorybrowser/directorybrowser.js | 2 +- src/components/displaysettings/displaysettings.js | 2 +- src/components/filtermenu/filtermenu.js | 2 +- src/components/homesections/homesections.js | 2 +- src/components/imagedownloader/imagedownloader.js | 2 +- src/components/maintabsmanager.js | 2 +- src/components/mediainfo/mediainfo.js | 2 +- src/components/medialibrarycreator/medialibrarycreator.js | 2 +- src/components/search/searchresults.js | 2 +- src/components/sortmenu/sortmenu.js | 2 +- src/components/tvproviders/schedulesdirect.js | 2 +- src/components/viewsettings/viewsettings.js | 2 +- src/controllers/addpluginpage.js | 2 +- src/controllers/addserver.js | 2 +- src/controllers/dashboardgeneral.js | 2 +- src/controllers/dashboardpage.js | 2 +- src/controllers/devices.js | 2 +- src/controllers/itemdetailpage.js | 2 +- src/controllers/librarydisplay.js | 2 +- src/controllers/librarysettings.js | 2 +- src/controllers/logpage.js | 2 +- src/controllers/mypreferencescommon.js | 2 +- src/controllers/myprofile.js | 2 +- src/controllers/notificationsettings.js | 2 +- src/controllers/plugincatalogpage.js | 2 +- src/controllers/scheduledtaskspage.js | 2 +- src/controllers/userpasswordpage.js | 2 +- src/controllers/wizarduserpage.js | 2 +- src/scripts/dlnaprofile.js | 2 +- src/scripts/dlnaprofiles.js | 2 +- src/scripts/itembynamedetailpage.js | 2 +- src/scripts/livetvsettings.js | 2 +- src/scripts/livetvstatus.js | 2 +- src/scripts/moviegenres.js | 2 +- src/scripts/pluginspage.js | 2 +- src/scripts/site.js | 3 +-- src/scripts/tvgenres.js | 2 +- src/scripts/userprofilespage.js | 2 +- src/scripts/wizardagreement.js | 2 +- 40 files changed, 40 insertions(+), 41 deletions(-) diff --git a/src/components/collectioneditor/collectioneditor.js b/src/components/collectioneditor/collectioneditor.js index 4473c661e7..8c14405330 100644 --- a/src/components/collectioneditor/collectioneditor.js +++ b/src/components/collectioneditor/collectioneditor.js @@ -1,4 +1,4 @@ -define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'emby-linkbutton', 'flexStyles'], function (dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize) { +define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'emby-button', 'flexStyles'], function (dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize) { 'use strict'; var currentServerId; diff --git a/src/components/directorybrowser/directorybrowser.js b/src/components/directorybrowser/directorybrowser.js index c6d811e959..35bc914301 100644 --- a/src/components/directorybrowser/directorybrowser.js +++ b/src/components/directorybrowser/directorybrowser.js @@ -1,4 +1,4 @@ -define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'emby-button', 'paper-icon-button-light', 'css!./directorybrowser', 'formDialogStyle', 'emby-linkbutton'], function(loading, dialogHelper, dom) { +define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'emby-button', 'paper-icon-button-light', 'css!./directorybrowser', 'formDialogStyle', 'emby-button'], function(loading, dialogHelper, dom) { 'use strict'; function getSystemInfo() { diff --git a/src/components/displaysettings/displaysettings.js b/src/components/displaysettings/displaysettings.js index a33dba8e07..680c6b634b 100644 --- a/src/components/displaysettings/displaysettings.js +++ b/src/components/displaysettings/displaysettings.js @@ -1,4 +1,4 @@ -define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', 'apphost', 'focusManager', 'datetime', 'globalize', 'loading', 'connectionManager', 'skinManager', 'dom', 'events', 'emby-select', 'emby-checkbox', 'emby-linkbutton'], function (require, browser, layoutManager, appSettings, pluginManager, appHost, focusManager, datetime, globalize, loading, connectionManager, skinManager, dom, events) { +define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', 'apphost', 'focusManager', 'datetime', 'globalize', 'loading', 'connectionManager', 'skinManager', 'dom', 'events', 'emby-select', 'emby-checkbox', 'emby-button'], function (require, browser, layoutManager, appSettings, pluginManager, appHost, focusManager, datetime, globalize, loading, connectionManager, skinManager, dom, events) { "use strict"; function fillThemes(select, isDashboard) { diff --git a/src/components/filtermenu/filtermenu.js b/src/components/filtermenu/filtermenu.js index 42bd101129..02b35880b9 100644 --- a/src/components/filtermenu/filtermenu.js +++ b/src/components/filtermenu/filtermenu.js @@ -1,4 +1,4 @@ -define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', 'inputManager', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'userSettings', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'emby-linkbutton', 'flexStyles'], function (require, dom, focusManager, dialogHelper, loading, appHost, inputManager, layoutManager, connectionManager, appRouter, globalize, userSettings) { +define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', 'inputManager', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'userSettings', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'emby-button', 'flexStyles'], function (require, dom, focusManager, dialogHelper, loading, appHost, inputManager, layoutManager, connectionManager, appRouter, globalize, userSettings) { 'use strict'; function onSubmit(e) { diff --git a/src/components/homesections/homesections.js b/src/components/homesections/homesections.js index 9c2ec05aac..bf2a05ffba 100644 --- a/src/components/homesections/homesections.js +++ b/src/components/homesections/homesections.js @@ -1,4 +1,4 @@ -define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'layoutManager', 'imageLoader', 'globalize', 'itemShortcuts', 'itemHelper', 'appRouter', 'emby-button', 'paper-icon-button-light', 'emby-itemscontainer', 'emby-scroller', 'emby-linkbutton', 'css!./homesections'], function (connectionManager, cardBuilder, appSettings, dom, appHost, layoutManager, imageLoader, globalize, itemShortcuts, itemHelper, appRouter) { +define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'layoutManager', 'imageLoader', 'globalize', 'itemShortcuts', 'itemHelper', 'appRouter', 'emby-button', 'paper-icon-button-light', 'emby-itemscontainer', 'emby-scroller', 'emby-button', 'css!./homesections'], function (connectionManager, cardBuilder, appSettings, dom, appHost, layoutManager, imageLoader, globalize, itemShortcuts, itemHelper, appRouter) { 'use strict'; function getDefaultSection(index) { diff --git a/src/components/imagedownloader/imagedownloader.js b/src/components/imagedownloader/imagedownloader.js index f24acbb655..9c6aab2725 100644 --- a/src/components/imagedownloader/imagedownloader.js +++ b/src/components/imagedownloader/imagedownloader.js @@ -1,4 +1,4 @@ -define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader', 'browser', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'emby-checkbox', 'emby-button', 'paper-icon-button-light', 'emby-linkbutton', 'formDialogStyle', 'cardStyle'], function (loading, appHost, dialogHelper, connectionManager, imageLoader, browser, layoutManager, scrollHelper, globalize, require) { +define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader', 'browser', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'emby-checkbox', 'emby-button', 'paper-icon-button-light', 'emby-button', 'formDialogStyle', 'cardStyle'], function (loading, appHost, dialogHelper, connectionManager, imageLoader, browser, layoutManager, scrollHelper, globalize, require) { 'use strict'; var currentItemId; diff --git a/src/components/maintabsmanager.js b/src/components/maintabsmanager.js index b8da631df9..fa2922aafb 100644 --- a/src/components/maintabsmanager.js +++ b/src/components/maintabsmanager.js @@ -1,4 +1,4 @@ -define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button', 'emby-linkbutton'], function (dom, browser, events) { +define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button', 'emby-button'], function (dom, browser, events) { 'use strict'; var tabOwnerView; diff --git a/src/components/mediainfo/mediainfo.js b/src/components/mediainfo/mediainfo.js index 3f92425034..441adac3dd 100644 --- a/src/components/mediainfo/mediainfo.js +++ b/src/components/mediainfo/mediainfo.js @@ -1,4 +1,4 @@ -define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'material-icons', 'css!./mediainfo.css', 'programStyles', 'emby-linkbutton'], function (datetime, globalize, appRouter, itemHelper, indicators) { +define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'material-icons', 'css!./mediainfo.css', 'programStyles', 'emby-button'], function (datetime, globalize, appRouter, itemHelper, indicators) { 'use strict'; function getTimerIndicator(item) { diff --git a/src/components/medialibrarycreator/medialibrarycreator.js b/src/components/medialibrarycreator/medialibrarycreator.js index af51d2ef54..d02f0940cb 100644 --- a/src/components/medialibrarycreator/medialibrarycreator.js +++ b/src/components/medialibrarycreator/medialibrarycreator.js @@ -1,4 +1,4 @@ -define(["loading", "dialogHelper", "dom", "jQuery", "components/libraryoptionseditor/libraryoptionseditor", "emby-toggle", "emby-input", "emby-select", "paper-icon-button-light", "listViewStyle", "formDialogStyle", "emby-linkbutton", "flexStyles"], function(loading, dialogHelper, dom, $, libraryoptionseditor) { +define(["loading", "dialogHelper", "dom", "jQuery", "components/libraryoptionseditor/libraryoptionseditor", "emby-toggle", "emby-input", "emby-select", "paper-icon-button-light", "listViewStyle", "formDialogStyle", "emby-button", "flexStyles"], function(loading, dialogHelper, dom, $, libraryoptionseditor) { "use strict"; function onSubmit(e) { diff --git a/src/components/search/searchresults.js b/src/components/search/searchresults.js index 1b8161d333..e42088c066 100644 --- a/src/components/search/searchresults.js +++ b/src/components/search/searchresults.js @@ -1,4 +1,4 @@ -define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', 'cardBuilder', 'appRouter', 'emby-scroller', 'emby-itemscontainer', 'emby-linkbutton'], function (layoutManager, globalize, require, events, connectionManager, cardBuilder, appRouter) { +define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', 'cardBuilder', 'appRouter', 'emby-scroller', 'emby-itemscontainer', 'emby-button'], function (layoutManager, globalize, require, events, connectionManager, cardBuilder, appRouter) { 'use strict'; function loadSuggestions(instance, context, apiClient) { diff --git a/src/components/sortmenu/sortmenu.js b/src/components/sortmenu/sortmenu.js index 90dc1790d1..06e75c59cc 100644 --- a/src/components/sortmenu/sortmenu.js +++ b/src/components/sortmenu/sortmenu.js @@ -1,4 +1,4 @@ -define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'layoutManager', 'connectionManager', 'globalize', 'userSettings', 'emby-select', 'paper-icon-button-light', 'material-icons', 'css!./../formdialog', 'emby-button', 'emby-linkbutton', 'flexStyles'], function (require, dom, focusManager, dialogHelper, loading, layoutManager, connectionManager, globalize, userSettings) { +define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'layoutManager', 'connectionManager', 'globalize', 'userSettings', 'emby-select', 'paper-icon-button-light', 'material-icons', 'css!./../formdialog', 'emby-button', 'emby-button', 'flexStyles'], function (require, dom, focusManager, dialogHelper, loading, layoutManager, connectionManager, globalize, userSettings) { 'use strict'; function onSubmit(e) { diff --git a/src/components/tvproviders/schedulesdirect.js b/src/components/tvproviders/schedulesdirect.js index 0eb54a472d..9af7e5be72 100644 --- a/src/components/tvproviders/schedulesdirect.js +++ b/src/components/tvproviders/schedulesdirect.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "emby-select", "emby-linkbutton", "flexStyles"], function($, loading) { +define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "emby-select", "emby-button", "flexStyles"], function($, loading) { "use strict"; return function(page, providerId, options) { function reload() { diff --git a/src/components/viewsettings/viewsettings.js b/src/components/viewsettings/viewsettings.js index af2167fa6f..bfeb7e66ff 100644 --- a/src/components/viewsettings/viewsettings.js +++ b/src/components/viewsettings/viewsettings.js @@ -1,4 +1,4 @@ -define(['require', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'userSettings', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'emby-linkbutton', 'flexStyles'], function (require, dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize, userSettings) { +define(['require', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'userSettings', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'emby-button', 'flexStyles'], function (require, dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize, userSettings) { 'use strict'; function onSubmit(e) { diff --git a/src/controllers/addpluginpage.js b/src/controllers/addpluginpage.js index 6ad5b05d3f..32f71b8027 100644 --- a/src/controllers/addpluginpage.js +++ b/src/controllers/addpluginpage.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "emby-linkbutton"], function($, loading, libraryMenu, globalize, connectionManager) { +define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "emby-button"], function($, loading, libraryMenu, globalize, connectionManager) { "use strict"; function populateHistory(packageInfo, page) { diff --git a/src/controllers/addserver.js b/src/controllers/addserver.js index 3afb9c68a8..45fa427420 100644 --- a/src/controllers/addserver.js +++ b/src/controllers/addserver.js @@ -1,4 +1,4 @@ -define(["appSettings", "loading", "browser", "emby-linkbutton"], function(appSettings, loading, browser) { +define(["appSettings", "loading", "browser", "emby-button"], function(appSettings, loading, browser) { "use strict"; function handleConnectionResult(page, result) { diff --git a/src/controllers/dashboardgeneral.js b/src/controllers/dashboardgeneral.js index c02717fdbb..09aa1ec08e 100644 --- a/src/controllers/dashboardgeneral.js +++ b/src/controllers/dashboardgeneral.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emby-input", "emby-select", "emby-linkbutton"], function($, loading) { +define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emby-input", "emby-select", "emby-button"], function($, loading) { "use strict"; function loadPage(page, config, languageOptions, systemInfo) { diff --git a/src/controllers/dashboardpage.js b/src/controllers/dashboardpage.js index c0a363d65c..446a7c6d6f 100644 --- a/src/controllers/dashboardpage.js +++ b/src/controllers/dashboardpage.js @@ -1,4 +1,4 @@ -define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globalize", "loading", "connectionManager", "playMethodHelper", "cardBuilder", "imageLoader", "components/activitylog", "humanedate", "listViewStyle", "emby-linkbutton", "flexStyles", "emby-button", "emby-itemscontainer"], function (datetime, events, itemHelper, serverNotifications, dom, globalize, loading, connectionManager, playMethodHelper, cardBuilder, imageLoader, ActivityLog) { +define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globalize", "loading", "connectionManager", "playMethodHelper", "cardBuilder", "imageLoader", "components/activitylog", "humanedate", "listViewStyle", "emby-button", "flexStyles", "emby-button", "emby-itemscontainer"], function (datetime, events, itemHelper, serverNotifications, dom, globalize, loading, connectionManager, playMethodHelper, cardBuilder, imageLoader, ActivityLog) { "use strict"; function buttonEnabled(elem, enabled) { diff --git a/src/controllers/devices.js b/src/controllers/devices.js index e5e5d16dc7..e4c2f6b44b 100644 --- a/src/controllers/devices.js +++ b/src/controllers/devices.js @@ -1,4 +1,4 @@ -define(["loading", "dom", "libraryMenu", "globalize", "humanedate", "emby-linkbutton", "emby-itemscontainer", "cardStyle"], function(loading, dom, libraryMenu, globalize) { +define(["loading", "dom", "libraryMenu", "globalize", "humanedate", "emby-button", "emby-itemscontainer", "cardStyle"], function(loading, dom, libraryMenu, globalize) { "use strict"; function canDelete(deviceId) { diff --git a/src/controllers/itemdetailpage.js b/src/controllers/itemdetailpage.js index 685927a09d..3a0e776d3f 100644 --- a/src/controllers/itemdetailpage.js +++ b/src/controllers/itemdetailpage.js @@ -1,4 +1,4 @@ -define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuilder", "datetime", "mediaInfo", "backdrop", "listView", "itemContextMenu", "itemHelper", "dom", "indicators", "apphost", "imageLoader", "libraryMenu", "globalize", "browser", "events", "scrollHelper", "playbackManager", "libraryBrowser", "scrollStyles", "emby-itemscontainer", "emby-checkbox", "emby-linkbutton", "emby-playstatebutton", "emby-ratingbutton", "emby-scroller", "emby-select"], function(loading, appRouter, layoutManager, connectionManager, cardBuilder, datetime, mediaInfo, backdrop, listView, itemContextMenu, itemHelper, dom, indicators, appHost, imageLoader, libraryMenu, globalize, browser, events, scrollHelper, playbackManager, libraryBrowser) { +define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuilder", "datetime", "mediaInfo", "backdrop", "listView", "itemContextMenu", "itemHelper", "dom", "indicators", "apphost", "imageLoader", "libraryMenu", "globalize", "browser", "events", "scrollHelper", "playbackManager", "libraryBrowser", "scrollStyles", "emby-itemscontainer", "emby-checkbox", "emby-button", "emby-playstatebutton", "emby-ratingbutton", "emby-scroller", "emby-select"], function(loading, appRouter, layoutManager, connectionManager, cardBuilder, datetime, mediaInfo, backdrop, listView, itemContextMenu, itemHelper, dom, indicators, appHost, imageLoader, libraryMenu, globalize, browser, events, scrollHelper, playbackManager, libraryBrowser) { "use strict"; function getPromise(apiClient, params) { diff --git a/src/controllers/librarydisplay.js b/src/controllers/librarydisplay.js index 924641d743..80f5bbc09b 100644 --- a/src/controllers/librarydisplay.js +++ b/src/controllers/librarydisplay.js @@ -1,4 +1,4 @@ -define(["globalize", "loading", "libraryMenu", "emby-checkbox", "emby-button", "emby-linkbutton"], function(globalize, loading, libraryMenu) { +define(["globalize", "loading", "libraryMenu", "emby-checkbox", "emby-button", "emby-button"], function(globalize, loading, libraryMenu) { "use strict"; function getTabs() { diff --git a/src/controllers/librarysettings.js b/src/controllers/librarysettings.js index 5e700b6fb0..997ccdfd4d 100644 --- a/src/controllers/librarysettings.js +++ b/src/controllers/librarysettings.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "libraryMenu", "fnchecked", "emby-checkbox", "emby-linkbutton"], function($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu", "fnchecked", "emby-checkbox", "emby-button"], function($, loading, libraryMenu) { "use strict"; function loadPage(page, config) { diff --git a/src/controllers/logpage.js b/src/controllers/logpage.js index 0c29389255..4b288b288f 100644 --- a/src/controllers/logpage.js +++ b/src/controllers/logpage.js @@ -1,4 +1,4 @@ -define(["datetime", "loading", "apphost", "listViewStyle", "emby-linkbutton", "flexStyles"], function(datetime, loading, appHost) { +define(["datetime", "loading", "apphost", "listViewStyle", "emby-button", "flexStyles"], function(datetime, loading, appHost) { "use strict"; return function(view, params) { view.querySelector("#chkDebugLog").addEventListener("change", function() { diff --git a/src/controllers/mypreferencescommon.js b/src/controllers/mypreferencescommon.js index c30d6f723a..e52fcc1b34 100644 --- a/src/controllers/mypreferencescommon.js +++ b/src/controllers/mypreferencescommon.js @@ -1,4 +1,4 @@ -define(["apphost", "connectionManager", "listViewStyle", "emby-linkbutton"], function(appHost, connectionManager) { +define(["apphost", "connectionManager", "listViewStyle", "emby-button"], function(appHost, connectionManager) { "use strict"; return function(view, params) { diff --git a/src/controllers/myprofile.js b/src/controllers/myprofile.js index 71baf40a41..be8f1b446e 100644 --- a/src/controllers/myprofile.js +++ b/src/controllers/myprofile.js @@ -1,4 +1,4 @@ -define(["controllers/userpasswordpage", "loading", "libraryMenu", "apphost", "emby-linkbutton"], function (Userpasswordpage, loading, libraryMenu, appHost) { +define(["controllers/userpasswordpage", "loading", "libraryMenu", "apphost", "emby-button"], function (Userpasswordpage, loading, libraryMenu, appHost) { "use strict"; function reloadUser(page) { diff --git a/src/controllers/notificationsettings.js b/src/controllers/notificationsettings.js index b167ca00e4..092d92e24b 100644 --- a/src/controllers/notificationsettings.js +++ b/src/controllers/notificationsettings.js @@ -1,4 +1,4 @@ -define(["loading", "libraryMenu", "globalize", "listViewStyle", "emby-linkbutton"], function(loading, libraryMenu, globalize) { +define(["loading", "libraryMenu", "globalize", "listViewStyle", "emby-button"], function(loading, libraryMenu, globalize) { "use strict"; function reload(page) { diff --git a/src/controllers/plugincatalogpage.js b/src/controllers/plugincatalogpage.js index b399ba098a..c823d7c372 100644 --- a/src/controllers/plugincatalogpage.js +++ b/src/controllers/plugincatalogpage.js @@ -1,4 +1,4 @@ -define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-linkbutton", "emby-checkbox", "emby-select"], function (loading, libraryMenu, globalize) { +define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-button", "emby-checkbox", "emby-select"], function (loading, libraryMenu, globalize) { "use strict"; function reloadList(page) { diff --git a/src/controllers/scheduledtaskspage.js b/src/controllers/scheduledtaskspage.js index 50c2ef53a0..1580f1a4c3 100644 --- a/src/controllers/scheduledtaskspage.js +++ b/src/controllers/scheduledtaskspage.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "events", "globalize", "serverNotifications", "humanedate", "listViewStyle", "emby-linkbutton"], function($, loading, events, globalize, serverNotifications) { +define(["jQuery", "loading", "events", "globalize", "serverNotifications", "humanedate", "listViewStyle", "emby-button"], function($, loading, events, globalize, serverNotifications) { "use strict"; function reloadList(page) { diff --git a/src/controllers/userpasswordpage.js b/src/controllers/userpasswordpage.js index 478ba95724..d1eef004f6 100644 --- a/src/controllers/userpasswordpage.js +++ b/src/controllers/userpasswordpage.js @@ -1,4 +1,4 @@ -define(["loading", "libraryMenu", "emby-linkbutton"], function(loading, libraryMenu) { +define(["loading", "libraryMenu", "emby-button"], function(loading, libraryMenu) { "use strict"; function loadUser(page, params) { diff --git a/src/controllers/wizarduserpage.js b/src/controllers/wizarduserpage.js index c3508efc12..a3654edf0e 100644 --- a/src/controllers/wizarduserpage.js +++ b/src/controllers/wizarduserpage.js @@ -1,4 +1,4 @@ -define(["loading", "globalize", "dashboardcss", "emby-input", "emby-button", "emby-linkbutton"], function(loading, globalize) { +define(["loading", "globalize", "dashboardcss", "emby-input", "emby-button", "emby-button"], function(loading, globalize) { "use strict"; function getApiClient() { diff --git a/src/scripts/dlnaprofile.js b/src/scripts/dlnaprofile.js index f9d72a3540..026c228d2d 100644 --- a/src/scripts/dlnaprofile.js +++ b/src/scripts/dlnaprofile.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-input", "emby-checkbox", "listViewStyle", "emby-linkbutton"], function($, loading) { +define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-input", "emby-checkbox", "listViewStyle", "emby-button"], function($, loading) { "use strict"; function loadProfile(page) { diff --git a/src/scripts/dlnaprofiles.js b/src/scripts/dlnaprofiles.js index 1f0fd1e791..b77b31e3b3 100644 --- a/src/scripts/dlnaprofiles.js +++ b/src/scripts/dlnaprofiles.js @@ -1,4 +1,4 @@ -define(["jQuery", "globalize", "loading", "libraryMenu", "listViewStyle", "emby-linkbutton"], function($, globalize, loading, libraryMenu) { +define(["jQuery", "globalize", "loading", "libraryMenu", "listViewStyle", "emby-button"], function($, globalize, loading, libraryMenu) { "use strict"; function loadProfiles(page) { diff --git a/src/scripts/itembynamedetailpage.js b/src/scripts/itembynamedetailpage.js index 31abfdfc31..727532a386 100644 --- a/src/scripts/itembynamedetailpage.js +++ b/src/scripts/itembynamedetailpage.js @@ -1,4 +1,4 @@ -define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryBrowser", "emby-itemscontainer", "emby-linkbutton"], function(connectionManager, listView, cardBuilder, imageLoader, libraryBrowser) { +define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryBrowser", "emby-itemscontainer", "emby-button"], function(connectionManager, listView, cardBuilder, imageLoader, libraryBrowser) { "use strict"; function renderItems(page, item) { diff --git a/src/scripts/livetvsettings.js b/src/scripts/livetvsettings.js index 4d659ad6b4..422257e33d 100644 --- a/src/scripts/livetvsettings.js +++ b/src/scripts/livetvsettings.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "fnchecked", "emby-linkbutton"], function($, loading) { +define(["jQuery", "loading", "fnchecked", "emby-button"], function($, loading) { "use strict"; function loadPage(page, config) { diff --git a/src/scripts/livetvstatus.js b/src/scripts/livetvstatus.js index 3a7078ccd8..1ed1402d6d 100644 --- a/src/scripts/livetvstatus.js +++ b/src/scripts/livetvstatus.js @@ -1,4 +1,4 @@ -define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layoutManager", "loading", "listViewStyle", "flexStyles", "emby-itemscontainer", "cardStyle", "material-icons", "emby-linkbutton"], function($, globalize, taskButton, dom, libraryMenu, layoutManager, loading) { +define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layoutManager", "loading", "listViewStyle", "flexStyles", "emby-itemscontainer", "cardStyle", "material-icons", "emby-button"], function($, globalize, taskButton, dom, libraryMenu, layoutManager, loading) { "use strict"; function getDeviceHtml(device) { diff --git a/src/scripts/moviegenres.js b/src/scripts/moviegenres.js index baac9fbc8c..b3a313a06d 100644 --- a/src/scripts/moviegenres.js +++ b/src/scripts/moviegenres.js @@ -1,4 +1,4 @@ -define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader", "apphost", "globalize", "appRouter", "dom", "emby-linkbutton"], function(layoutManager, loading, libraryBrowser, cardBuilder, lazyLoader, appHost, globalize, appRouter, dom) { +define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader", "apphost", "globalize", "appRouter", "dom", "emby-button"], function(layoutManager, loading, libraryBrowser, cardBuilder, lazyLoader, appHost, globalize, appRouter, dom) { "use strict"; return function(view, params, tabContent) { function getPageData() { diff --git a/src/scripts/pluginspage.js b/src/scripts/pluginspage.js index 6264f012e0..86f49d809c 100644 --- a/src/scripts/pluginspage.js +++ b/src/scripts/pluginspage.js @@ -1,4 +1,4 @@ -define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-linkbutton"], function(loading, libraryMenu, dom, globalize) { +define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button"], function(loading, libraryMenu, dom, globalize) { "use strict"; function deletePlugin(page, uniqueid, name) { diff --git a/src/scripts/site.js b/src/scripts/site.js index 6eb45b86d9..d1812e2e89 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -743,7 +743,6 @@ var AppInfo = {}; define("libraryMenu", ["scripts/librarymenu"], returnFirstDependency); define("emby-collapse", [componentsPath + "/emby-collapse/emby-collapse"], returnFirstDependency); define("emby-button", [componentsPath + "/emby-button/emby-button"], returnFirstDependency); - define("emby-linkbutton", ["emby-button"], returnFirstDependency); define("emby-itemscontainer", [componentsPath + "/emby-itemscontainer/emby-itemscontainer"], returnFirstDependency); define("alphaNumericShortcuts", [componentsPath + "/alphanumericshortcuts/alphanumericshortcuts"], returnFirstDependency); define("emby-scroller", [componentsPath + "/emby-scroller/emby-scroller"], returnFirstDependency); @@ -882,7 +881,7 @@ var AppInfo = {}; return jQuery; }); define("fnchecked", ["legacy/fnchecked"], returnFirstDependency); - define("dialogHelper", [componentsPath + "/dialoghelper/dialoghelper"], returnFirstDependency); + define("dialogHelper", [componentsPath + "/dialogHelper/dialogHelper"], returnFirstDependency); define("inputmanager", ["inputManager"], returnFirstDependency); define("serverNotifications", [componentsPath + "/apiInput/apiInput"], returnFirstDependency); define("headroom-window", ["headroom"], createWindowHeadroom); diff --git a/src/scripts/tvgenres.js b/src/scripts/tvgenres.js index 39191edd81..8a5d769969 100644 --- a/src/scripts/tvgenres.js +++ b/src/scripts/tvgenres.js @@ -1,4 +1,4 @@ -define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader", "apphost", "globalize", "appRouter", "dom", "emby-linkbutton"], function(layoutManager, loading, libraryBrowser, cardBuilder, lazyLoader, appHost, globalize, appRouter, dom) { +define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader", "apphost", "globalize", "appRouter", "dom", "emby-button"], function(layoutManager, loading, libraryBrowser, cardBuilder, lazyLoader, appHost, globalize, appRouter, dom) { "use strict"; return function(view, params, tabContent) { function getPageData() { diff --git a/src/scripts/userprofilespage.js b/src/scripts/userprofilespage.js index e34ad45412..c0d1d0d87b 100644 --- a/src/scripts/userprofilespage.js +++ b/src/scripts/userprofilespage.js @@ -1,4 +1,4 @@ -define(["loading", "dom", "globalize", "humanedate", "paper-icon-button-light", "cardStyle", "emby-linkbutton", "indicators", "flexStyles"], function (loading, dom, globalize) { +define(["loading", "dom", "globalize", "humanedate", "paper-icon-button-light", "cardStyle", "emby-button", "indicators", "flexStyles"], function (loading, dom, globalize) { "use strict"; function deleteUser(page, id) { diff --git a/src/scripts/wizardagreement.js b/src/scripts/wizardagreement.js index dfb9d70646..77c12fb664 100644 --- a/src/scripts/wizardagreement.js +++ b/src/scripts/wizardagreement.js @@ -1,4 +1,4 @@ -define(["dom", "emby-linkbutton"], function(dom) { +define(["dom", "emby-button"], function(dom) { "use strict"; function onSubmit(e) { From c2555d071dd5a18691230dfb856fc772fc7638c1 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Wed, 27 Feb 2019 22:29:33 +0000 Subject: [PATCH 168/220] added package.json for modules resolution --- src/components/emby-radio/package.json | 3 +++ src/components/emby-tabs/package.json | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 src/components/emby-radio/package.json create mode 100644 src/components/emby-tabs/package.json diff --git a/src/components/emby-radio/package.json b/src/components/emby-radio/package.json new file mode 100644 index 0000000000..2c1b97bd32 --- /dev/null +++ b/src/components/emby-radio/package.json @@ -0,0 +1,3 @@ +{ + "main": "emby-radio.js" +} \ No newline at end of file diff --git a/src/components/emby-tabs/package.json b/src/components/emby-tabs/package.json new file mode 100644 index 0000000000..0813d041c7 --- /dev/null +++ b/src/components/emby-tabs/package.json @@ -0,0 +1,3 @@ +{ + "main": "emby-tabs.js" +} \ No newline at end of file From ecf316d67100768bc2b609f9c4cd393e8fada1e2 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Wed, 27 Feb 2019 22:30:13 +0000 Subject: [PATCH 169/220] removed polyfill fetch --- src/bower_components/fetch/fetch.js | 263 ---------------------------- src/scripts/site.js | 5 - 2 files changed, 268 deletions(-) delete mode 100644 src/bower_components/fetch/fetch.js diff --git a/src/bower_components/fetch/fetch.js b/src/bower_components/fetch/fetch.js deleted file mode 100644 index cd40b3ed2d..0000000000 --- a/src/bower_components/fetch/fetch.js +++ /dev/null @@ -1,263 +0,0 @@ -! function(self) { - "use strict"; - - function normalizeName(name) { - if ("string" != typeof name && (name = String(name)), /[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) throw new TypeError("Invalid character in header field name"); - return name.toLowerCase() - } - - function normalizeValue(value) { - return "string" != typeof value && (value = String(value)), value - } - - function iteratorFor(items) { - var iterator = { - next: function() { - var value = items.shift(); - return { - done: void 0 === value, - value: value - } - } - }; - return support.iterable && (iterator[Symbol.iterator] = function() { - return iterator - }), iterator - } - - function Headers(headers) { - this.map = {}, headers instanceof Headers ? headers.forEach(function(value, name) { - this.append(name, value) - }, this) : headers && Object.getOwnPropertyNames(headers).forEach(function(name) { - this.append(name, headers[name]) - }, this) - } - - function consumed(body) { - if (body.bodyUsed) return Promise.reject(new TypeError("Already read")); - body.bodyUsed = !0 - } - - function fileReaderReady(reader) { - return new Promise(function(resolve, reject) { - reader.onload = function() { - resolve(reader.result) - }, reader.onerror = function() { - reject(reader.error) - } - }) - } - - function readBlobAsArrayBuffer(blob) { - var reader = new FileReader, - promise = fileReaderReady(reader); - return reader.readAsArrayBuffer(blob), promise - } - - function readBlobAsText(blob) { - var reader = new FileReader, - promise = fileReaderReady(reader); - return reader.readAsText(blob), promise - } - - function readArrayBufferAsText(buf) { - for (var view = new Uint8Array(buf), chars = new Array(view.length), i = 0; i < view.length; i++) chars[i] = String.fromCharCode(view[i]); - return chars.join("") - } - - function bufferClone(buf) { - if (buf.slice) return buf.slice(0); - var view = new Uint8Array(buf.byteLength); - return view.set(new Uint8Array(buf)), view.buffer - } - - function Body() { - return this.bodyUsed = !1, this._initBody = function(body) { - if (this._bodyInit = body, body) - if ("string" == typeof body) this._bodyText = body; - else if (support.blob && Blob.prototype.isPrototypeOf(body)) this._bodyBlob = body; - else if (support.formData && FormData.prototype.isPrototypeOf(body)) this._bodyFormData = body; - else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) this._bodyText = body.toString(); - else if (support.arrayBuffer && support.blob && isDataView(body)) this._bodyArrayBuffer = bufferClone(body.buffer), this._bodyInit = new Blob([this._bodyArrayBuffer]); - else { - if (!support.arrayBuffer || !ArrayBuffer.prototype.isPrototypeOf(body) && !isArrayBufferView(body)) throw new Error("unsupported BodyInit type"); - this._bodyArrayBuffer = bufferClone(body) - } else this._bodyText = ""; - this.headers.get("content-type") || ("string" == typeof body ? this.headers.set("content-type", "text/plain;charset=UTF-8") : this._bodyBlob && this._bodyBlob.type ? this.headers.set("content-type", this._bodyBlob.type) : support.searchParams && URLSearchParams.prototype.isPrototypeOf(body) && this.headers.set("content-type", "application/x-www-form-urlencoded;charset=UTF-8")) - }, support.blob && (this.blob = function() { - var rejected = consumed(this); - if (rejected) return rejected; - if (this._bodyBlob) return Promise.resolve(this._bodyBlob); - if (this._bodyArrayBuffer) return Promise.resolve(new Blob([this._bodyArrayBuffer])); - if (this._bodyFormData) throw new Error("could not read FormData body as blob"); - return Promise.resolve(new Blob([this._bodyText])) - }, this.arrayBuffer = function() { - return this._bodyArrayBuffer ? consumed(this) || Promise.resolve(this._bodyArrayBuffer) : this.blob().then(readBlobAsArrayBuffer) - }), this.text = function() { - var rejected = consumed(this); - if (rejected) return rejected; - if (this._bodyBlob) return readBlobAsText(this._bodyBlob); - if (this._bodyArrayBuffer) return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer)); - if (this._bodyFormData) throw new Error("could not read FormData body as text"); - return Promise.resolve(this._bodyText) - }, support.formData && (this.formData = function() { - return this.text().then(decode) - }), this.json = function() { - return this.text().then(JSON.parse) - }, this - } - - function normalizeMethod(method) { - var upcased = method.toUpperCase(); - return methods.indexOf(upcased) > -1 ? upcased : method - } - - function Request(input, options) { - options = options || {}; - var body = options.body; - if ("string" == typeof input) this.url = input; - else { - if (input.bodyUsed) throw new TypeError("Already read"); - this.url = input.url, this.credentials = input.credentials, options.headers || (this.headers = new Headers(input.headers)), this.method = input.method, this.mode = input.mode, body || null == input._bodyInit || (body = input._bodyInit, input.bodyUsed = !0) - } - if (this.credentials = options.credentials || this.credentials || "omit", !options.headers && this.headers || (this.headers = new Headers(options.headers)), this.method = normalizeMethod(options.method || this.method || "GET"), this.mode = options.mode || this.mode || null, this.referrer = null, ("GET" === this.method || "HEAD" === this.method) && body) throw new TypeError("Body not allowed for GET or HEAD requests"); - this._initBody(body) - } - - function decode(body) { - var form = new FormData; - return body.trim().split("&").forEach(function(bytes) { - if (bytes) { - var split = bytes.split("="), - name = split.shift().replace(/\+/g, " "), - value = split.join("=").replace(/\+/g, " "); - form.append(decodeURIComponent(name), decodeURIComponent(value)) - } - }), form - } - - function parseHeaders(rawHeaders) { - var headers = new Headers; - return rawHeaders.split("\r\n").forEach(function(line) { - var parts = line.split(":"), - key = parts.shift().trim(); - if (key) { - var value = parts.join(":").trim(); - headers.append(key, value) - } - }), headers - } - - function Response(bodyInit, options) { - options || (options = {}), this.type = "default", this.status = "status" in options ? options.status : 200, this.ok = this.status >= 200 && this.status < 300, this.statusText = "statusText" in options ? options.statusText : "OK", this.headers = new Headers(options.headers), this.url = options.url || "", this._initBody(bodyInit) - } - if (!self.fetch) { - var support = { - searchParams: "URLSearchParams" in self, - iterable: "Symbol" in self && "iterator" in Symbol, - blob: "FileReader" in self && "Blob" in self && function() { - try { - return new Blob, !0 - } catch (e) { - return !1 - } - }(), - formData: "FormData" in self, - arrayBuffer: "ArrayBuffer" in self - }; - if (support.arrayBuffer) var viewClasses = ["[object Int8Array]", "[object Uint8Array]", "[object Uint8ClampedArray]", "[object Int16Array]", "[object Uint16Array]", "[object Int32Array]", "[object Uint32Array]", "[object Float32Array]", "[object Float64Array]"], - isDataView = function(obj) { - return obj && DataView.prototype.isPrototypeOf(obj) - }, - isArrayBufferView = ArrayBuffer.isView || function(obj) { - return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1 - }; - Headers.prototype.append = function(name, value) { - name = normalizeName(name), value = normalizeValue(value); - var list = this.map[name]; - list || (list = [], this.map[name] = list), list.push(value) - }, Headers.prototype.delete = function(name) { - delete this.map[normalizeName(name)] - }, Headers.prototype.get = function(name) { - var values = this.map[normalizeName(name)]; - return values ? values[0] : null - }, Headers.prototype.getAll = function(name) { - return this.map[normalizeName(name)] || [] - }, Headers.prototype.has = function(name) { - return this.map.hasOwnProperty(normalizeName(name)) - }, Headers.prototype.set = function(name, value) { - this.map[normalizeName(name)] = [normalizeValue(value)] - }, Headers.prototype.forEach = function(callback, thisArg) { - Object.getOwnPropertyNames(this.map).forEach(function(name) { - this.map[name].forEach(function(value) { - callback.call(thisArg, value, name, this) - }, this) - }, this) - }, Headers.prototype.keys = function() { - var items = []; - return this.forEach(function(value, name) { - items.push(name) - }), iteratorFor(items) - }, Headers.prototype.values = function() { - var items = []; - return this.forEach(function(value) { - items.push(value) - }), iteratorFor(items) - }, Headers.prototype.entries = function() { - var items = []; - return this.forEach(function(value, name) { - items.push([name, value]) - }), iteratorFor(items) - }, support.iterable && (Headers.prototype[Symbol.iterator] = Headers.prototype.entries); - var methods = ["DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT"]; - Request.prototype.clone = function() { - return new Request(this, { - body: this._bodyInit - }) - }, Body.call(Request.prototype), Body.call(Response.prototype), Response.prototype.clone = function() { - return new Response(this._bodyInit, { - status: this.status, - statusText: this.statusText, - headers: new Headers(this.headers), - url: this.url - }) - }, Response.error = function() { - var response = new Response(null, { - status: 0, - statusText: "" - }); - return response.type = "error", response - }; - var redirectStatuses = [301, 302, 303, 307, 308]; - Response.redirect = function(url, status) { - if (-1 === redirectStatuses.indexOf(status)) throw new RangeError("Invalid status code"); - return new Response(null, { - status: status, - headers: { - location: url - } - }) - }, self.Headers = Headers, self.Request = Request, self.Response = Response, self.fetch = function(input, init) { - return new Promise(function(resolve, reject) { - var request = new Request(input, init), - xhr = new XMLHttpRequest; - xhr.onload = function() { - var options = { - status: xhr.status, - statusText: xhr.statusText, - headers: parseHeaders(xhr.getAllResponseHeaders() || "") - }; - options.url = "responseURL" in xhr ? xhr.responseURL : options.headers.get("X-Request-URL"); - var body = "response" in xhr ? xhr.response : xhr.responseText; - resolve(new Response(body, options)) - }, xhr.onerror = function() { - reject(new TypeError("Network request failed")) - }, xhr.ontimeout = function() { - reject(new TypeError("Network request failed")) - }, xhr.open(request.method, request.url, !0), "include" === request.credentials && (xhr.withCredentials = !0), "responseType" in xhr && support.blob && (xhr.responseType = "blob"), request.headers.forEach(function(value, name) { - xhr.setRequestHeader(name, value) - }), xhr.send(void 0 === request._bodyInit ? null : request._bodyInit) - }) - }, self.fetch.polyfill = !0 - } -}("undefined" != typeof self ? self : this); \ No newline at end of file diff --git a/src/scripts/site.js b/src/scripts/site.js index d1812e2e89..4e3c06548f 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -473,10 +473,6 @@ var AppInfo = {}; define("buttonenabled", ["legacy/buttonenabled"], returnFirstDependency); var promises = []; - if (!window.fetch) { - promises.push(require(["fetch"])); - } - Promise.all(promises).then(function () { createConnectionManager().then(function () { console.log("initAfterDependencies promises resolved"); @@ -834,7 +830,6 @@ var AppInfo = {}; define("jstree", ["thirdparty/jstree/jstree", "css!thirdparty/jstree/themes/default/style.css"], returnFirstDependency); define("dashboardcss", ["css!css/dashboard"], returnFirstDependency); define("slideshow", [componentsPath + "/slideshow/slideshow"], returnFirstDependency); - define("fetch", [bowerPath + "/fetch/fetch"], returnFirstDependency); define("clearButtonStyle", ["css!" + componentsPath + "/clearbutton"], returnFirstDependency); define("userdataButtons", [componentsPath + "/userdatabuttons/userdatabuttons"], returnFirstDependency); define("emby-playstatebutton", [componentsPath + "/userdatabuttons/emby-playstatebutton"], returnFirstDependency); From e0ac97c1096f803a14025515d614cb03d3bedab2 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Wed, 27 Feb 2019 22:38:10 +0000 Subject: [PATCH 170/220] remove duplicated component viewcontainer-lite --- .../viewmanager/viewcontainer-lite.js | 313 ------------------ src/scripts/site.js | 2 +- 2 files changed, 1 insertion(+), 314 deletions(-) delete mode 100644 src/components/viewmanager/viewcontainer-lite.js diff --git a/src/components/viewmanager/viewcontainer-lite.js b/src/components/viewmanager/viewcontainer-lite.js deleted file mode 100644 index 57c8fe926c..0000000000 --- a/src/components/viewmanager/viewcontainer-lite.js +++ /dev/null @@ -1,313 +0,0 @@ -define(['browser', 'dom', 'layoutManager', 'css!./viewcontainer-lite'], function (browser, dom, layoutManager) { - 'use strict'; - - var mainAnimatedPages = document.querySelector('.mainAnimatedPages'); - var allPages = []; - var currentUrls = []; - var pageContainerCount = 3; - var selectedPageIndex = -1; - - function enableAnimation() { - - // too slow - if (browser.tv) { - return false; - } - - return browser.supportsCssAnimation(); - } - - function findLastView(parent, className) { - - var nodes = parent.childNodes; - for (var i = nodes.length - 1; i >= 0; i--) { - var node = nodes[i]; - var classList = node.classList; - if (classList && classList.contains(className)) { - return node; - } - } - } - - function findViewBefore(elem, className) { - - var node = elem.previousSibling; - while (node) { - var classList = node.classList; - if (classList && classList.contains(className)) { - return node; - } - - node = node.previousSibling; - } - } - - function loadView(options) { - - if (options.cancel) { - return; - } - - cancelActiveAnimations(); - - var selected = selectedPageIndex; - var previousAnimatable = selected === -1 ? null : allPages[selected]; - var pageIndex = selected + 1; - - if (pageIndex >= pageContainerCount) { - pageIndex = 0; - } - - var viewHtml = options.view; - - var properties = []; - if (options.fullscreen) { - properties.push('fullscreen'); - } - - var currentPage = allPages[pageIndex]; - - var view; - - if (currentPage) { - triggerDestroy(currentPage); - currentPage.insertAdjacentHTML('beforebegin', viewHtml); - view = findViewBefore(currentPage, 'view'); - - mainAnimatedPages.removeChild(currentPage); - - } else { - mainAnimatedPages.insertAdjacentHTML('beforeend', viewHtml); - - view = findLastView(mainAnimatedPages, 'view'); - } - - view.classList.add('mainAnimatedPage'); - - if (properties.length) { - view.setAttribute('data-properties', properties.join(',')); - } - - if (options.type) { - view.setAttribute('data-type', options.type); - } - - allPages[pageIndex] = view; - - if (onBeforeChange) { - onBeforeChange(view, false, options); - } - - beforeAnimate(allPages, pageIndex, selected); - - // animate here - return animate(view, previousAnimatable, options.transition, options.isBack).then(function () { - - selectedPageIndex = pageIndex; - currentUrls[pageIndex] = options.url; - if (!options.cancel && previousAnimatable) { - afterAnimate(allPages, pageIndex); - } - - return view; - }); - } - - function beforeAnimate(allPages, newPageIndex, oldPageIndex) { - for (var i = 0, length = allPages.length; i < length; i++) { - if (newPageIndex === i || oldPageIndex === i) { - //allPages[i].classList.remove('hide'); - } else { - allPages[i].classList.add('hide'); - } - } - } - - function afterAnimate(allPages, newPageIndex) { - for (var i = 0, length = allPages.length; i < length; i++) { - if (newPageIndex === i) { - //allPages[i].classList.remove('hide'); - } else { - allPages[i].classList.add('hide'); - } - } - } - - function animate(newAnimatedPage, oldAnimatedPage, transition, isBack) { - - if (enableAnimation() && oldAnimatedPage) { - if (transition === 'slide') { - return slide(newAnimatedPage, oldAnimatedPage, transition, isBack); - } else if (transition === 'fade') { - return fade(newAnimatedPage, oldAnimatedPage, transition, isBack); - } else { - clearAnimation(newAnimatedPage); - if (oldAnimatedPage) { - clearAnimation(oldAnimatedPage); - } - } - } - - return Promise.resolve(); - } - - function clearAnimation(elem) { - setAnimation(elem, 'none'); - } - - function slide(newAnimatedPage, oldAnimatedPage, transition, isBack) { - - return new Promise(function (resolve, reject) { - - var duration = layoutManager.tv ? 450 : 160; - - var animations = []; - - if (oldAnimatedPage) { - if (isBack) { - setAnimation(oldAnimatedPage, 'view-slideright-r ' + duration + 'ms ease-out normal both'); - } else { - setAnimation(oldAnimatedPage, 'view-slideleft-r ' + duration + 'ms ease-out normal both'); - } - animations.push(oldAnimatedPage); - } - - if (isBack) { - setAnimation(newAnimatedPage, 'view-slideright ' + duration + 'ms ease-out normal both'); - } else { - setAnimation(newAnimatedPage, 'view-slideleft ' + duration + 'ms ease-out normal both'); - } - animations.push(newAnimatedPage); - - currentAnimations = animations; - - var onAnimationComplete = function () { - dom.removeEventListener(newAnimatedPage, dom.whichAnimationEvent(), onAnimationComplete, { - once: true - }); - resolve(); - }; - - dom.addEventListener(newAnimatedPage, dom.whichAnimationEvent(), onAnimationComplete, { - once: true - }); - }); - } - - function fade(newAnimatedPage, oldAnimatedPage, transition, isBack) { - - return new Promise(function (resolve, reject) { - - var duration = layoutManager.tv ? 450 : 270; - var animations = []; - - newAnimatedPage.style.opacity = 0; - setAnimation(newAnimatedPage, 'view-fadein ' + duration + 'ms ease-in normal both'); - animations.push(newAnimatedPage); - - if (oldAnimatedPage) { - setAnimation(oldAnimatedPage, 'view-fadeout ' + duration + 'ms ease-out normal both'); - animations.push(oldAnimatedPage); - } - - currentAnimations = animations; - - var onAnimationComplete = function () { - dom.removeEventListener(newAnimatedPage, dom.whichAnimationEvent(), onAnimationComplete, { - once: true - }); - resolve(); - }; - - dom.addEventListener(newAnimatedPage, dom.whichAnimationEvent(), onAnimationComplete, { - once: true - }); - }); - } - - function setAnimation(elem, value) { - - requestAnimationFrame(function () { - elem.style.animation = value; - }); - } - - var currentAnimations = []; - function cancelActiveAnimations() { - - var animations = currentAnimations; - for (var i = 0, length = animations.length; i < length; i++) { - animations[i].style.animation = 'none'; - } - } - - var onBeforeChange; - function setOnBeforeChange(fn) { - onBeforeChange = fn; - } - - function tryRestoreView(options) { - - var url = options.url; - var index = currentUrls.indexOf(url); - - if (index !== -1) { - - var animatable = allPages[index]; - var view = animatable; - - if (view) { - - if (options.cancel) { - return; - } - - cancelActiveAnimations(); - - var selected = selectedPageIndex; - var previousAnimatable = selected === -1 ? null : allPages[selected]; - - if (onBeforeChange) { - onBeforeChange(view, true, options); - } - - beforeAnimate(allPages, index, selected); - - animatable.classList.remove('hide'); - - return animate(animatable, previousAnimatable, options.transition, options.isBack).then(function () { - - selectedPageIndex = index; - if (!options.cancel && previousAnimatable) { - afterAnimate(allPages, index); - } - return view; - }); - } - } - - return Promise.reject(); - } - - function triggerDestroy(view) { - - view.dispatchEvent(new CustomEvent('viewdestroy', { - cancelable: false - })); - } - - function reset() { - - allPages = []; - currentUrls = []; - mainAnimatedPages.innerHTML = ''; - selectedPageIndex = -1; - } - - return { - loadView: loadView, - tryRestoreView: tryRestoreView, - reset: reset, - setOnBeforeChange: setOnBeforeChange - }; -}); \ No newline at end of file diff --git a/src/scripts/site.js b/src/scripts/site.js index 4e3c06548f..d951fd3c7e 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -864,7 +864,7 @@ var AppInfo = {}; define("imageUploader", [componentsPath + "/imageuploader/imageuploader"], returnFirstDependency); define("navdrawer", ["components/navdrawer/navdrawer"], returnFirstDependency); define("htmlMediaHelper", [componentsPath + "/htmlvideoplayer/htmlmediahelper"], returnFirstDependency); - define("viewcontainer", ["components/viewcontainer-lite", "css!" + componentsPath + "/viewmanager/viewcontainer-lite"], returnFirstDependency); + define("viewcontainer", ["components/viewcontainer-lite"], returnFirstDependency); define("queryString", [bowerPath + "/query-string/index"], function () { return queryString; }); From 86c19ee4a390dc9295a8c19474c0a2a3cc04d46d Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Wed, 27 Feb 2019 22:48:30 +0000 Subject: [PATCH 171/220] module resolution for fullscreenManager --- src/components/fullscreen/fullscreen-dc.js | 26 ------------------ ...lscreenmanager.js => fullscreenManager.js} | 27 ++++++++++++++++++- src/scripts/site.js | 8 ++---- 3 files changed, 28 insertions(+), 33 deletions(-) delete mode 100644 src/components/fullscreen/fullscreen-dc.js rename src/components/{fullscreen/fullscreenmanager.js => fullscreenManager.js} (76%) diff --git a/src/components/fullscreen/fullscreen-dc.js b/src/components/fullscreen/fullscreen-dc.js deleted file mode 100644 index bc12a6a76d..0000000000 --- a/src/components/fullscreen/fullscreen-dc.js +++ /dev/null @@ -1,26 +0,0 @@ -define(['dom', 'fullscreenManager'], function (dom, fullscreenManager) { - 'use strict'; - - function isTargetValid(target) { - - if (dom.parentWithTag(target, ['BUTTON', 'INPUT', 'TEXTAREA'])) { - return false; - } - - return true; - } - - dom.addEventListener(window, 'dblclick', function (e) { - - if (isTargetValid(e.target)) { - if (fullscreenManager.isFullScreen()) { - fullscreenManager.exitFullscreen(); - } else { - fullscreenManager.requestFullscreen(); - } - } - - }, { - passive: true - }); -}); \ No newline at end of file diff --git a/src/components/fullscreen/fullscreenmanager.js b/src/components/fullscreenManager.js similarity index 76% rename from src/components/fullscreen/fullscreenmanager.js rename to src/components/fullscreenManager.js index 5773e57d07..0a43a764a5 100644 --- a/src/components/fullscreen/fullscreenmanager.js +++ b/src/components/fullscreenManager.js @@ -1,4 +1,4 @@ -define(['events', 'dom'], function (events, dom) { +define(['events', 'dom', 'apphost', 'browser'], function (events, dom, appHost, browser) { 'use strict'; function fullscreenManager() { @@ -79,5 +79,30 @@ define(['events', 'dom'], function (events, dom) { passive: true }); + if (appHost.supports("fullscreenchange") && (browser.edgeUwp || -1 !== navigator.userAgent.toLowerCase().indexOf("electron"))) { + function isTargetValid(target) { + + if (dom.parentWithTag(target, ['BUTTON', 'INPUT', 'TEXTAREA'])) { + return false; + } + + return true; + } + + dom.addEventListener(window, 'dblclick', function (e) { + + if (isTargetValid(e.target)) { + if (manager.isFullScreen()) { + manager.exitFullscreen(); + } else { + manager.requestFullscreen(); + } + } + + }, { + passive: true + }); + } + return manager; }); diff --git a/src/scripts/site.js b/src/scripts/site.js index d951fd3c7e..12526a56b9 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -618,11 +618,7 @@ var AppInfo = {}; } } - require(["playerSelectionMenu"]); - - if (appHost.supports("fullscreenchange") && (browser.edgeUwp || -1 !== navigator.userAgent.toLowerCase().indexOf("electron"))) { - require(["fullscreen-doubleclick"]); - } + require(["playerSelectionMenu", "fullscreenManager"]); if (appHost.supports("sync")) { initLocalSyncEvents(); @@ -779,7 +775,7 @@ var AppInfo = {}; define("searchResults", [componentsPath + "/search/searchresults"], returnFirstDependency); define("upNextDialog", [componentsPath + "/upnextdialog/upnextdialog"], returnFirstDependency); define("fullscreen-doubleclick", [componentsPath + "/fullscreen/fullscreen-dc"], returnFirstDependency); - define("fullscreenManager", [componentsPath + "/fullscreen/fullscreenmanager", "events"], returnFirstDependency); + define("fullscreenManager", [componentsPath + "/fullscreenManager", "events"], returnFirstDependency); define("headroom", [componentsPath + "/headroom/headroom"], returnFirstDependency); define("subtitleAppearanceHelper", [componentsPath + "/subtitlesettings/subtitleappearancehelper"], returnFirstDependency); define("subtitleSettings", [componentsPath + "/subtitlesettings/subtitlesettings"], returnFirstDependency); From 00c875b8935cb3527ece83d397a18be84abd945c Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Wed, 27 Feb 2019 22:58:19 +0000 Subject: [PATCH 172/220] module resolution for headroom --- src/components/headroom/package.json | 3 +++ src/scripts/librarymenu.js | 2 +- src/scripts/site.js | 1 - 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 src/components/headroom/package.json diff --git a/src/components/headroom/package.json b/src/components/headroom/package.json new file mode 100644 index 0000000000..9c6c42c82a --- /dev/null +++ b/src/components/headroom/package.json @@ -0,0 +1,3 @@ +{ + "main": "headroom.js" +} \ No newline at end of file diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index 56339b7075..8ade3edb88 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -724,7 +724,7 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " } function initHeadRoom(elem) { - require(["headroom-window"], function (headroom) { + require(["headroom"], function (headroom) { headroom.add(elem); }); } diff --git a/src/scripts/site.js b/src/scripts/site.js index 12526a56b9..ff2e5449e2 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -875,7 +875,6 @@ var AppInfo = {}; define("dialogHelper", [componentsPath + "/dialogHelper/dialogHelper"], returnFirstDependency); define("inputmanager", ["inputManager"], returnFirstDependency); define("serverNotifications", [componentsPath + "/apiInput/apiInput"], returnFirstDependency); - define("headroom-window", ["headroom"], createWindowHeadroom); define("appFooter-shared", ["appFooter"], createSharedAppFooter); define("skinManager", [componentsPath + "/skinManager"], returnFirstDependency); define("connectionManager", [], function () { From 1ba0c7501e406efa041baaad74351f5d1bf56b8b Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Wed, 27 Feb 2019 22:58:36 +0000 Subject: [PATCH 173/220] remove debugger from loginpage.js --- src/controllers/loginpage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/loginpage.js b/src/controllers/loginpage.js index e848bfde46..fc8369c29a 100644 --- a/src/controllers/loginpage.js +++ b/src/controllers/loginpage.js @@ -87,7 +87,7 @@ define(["appSettings", "dom", "connectionManager", "loading", "cardStyle", "emby }), view.addEventListener("viewshow", function(e) { loading.show(); var apiClient = getApiClient(); - apiClient.getPublicUsers().then(function(users) {debugger; + apiClient.getPublicUsers().then(function(users) { if (users.length) { if (users[0].EnableAutoLogin) { authenticateUserByName(view, apiClient, users[0].Name, ""); From 4a5fc817fbf5c07bf22ba526a2f7f3c65a656b2a Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Wed, 27 Feb 2019 23:26:11 +0000 Subject: [PATCH 174/220] module resolution for viewManager --- src/components/viewmanager/package.json | 3 +++ src/scripts/site.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 src/components/viewmanager/package.json diff --git a/src/components/viewmanager/package.json b/src/components/viewmanager/package.json new file mode 100644 index 0000000000..819371af71 --- /dev/null +++ b/src/components/viewmanager/package.json @@ -0,0 +1,3 @@ +{ + "main": "viewManager.js" +} \ No newline at end of file diff --git a/src/scripts/site.js b/src/scripts/site.js index ff2e5449e2..cfd2d58f55 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -801,7 +801,7 @@ var AppInfo = {}; define("programStyles", ["css!" + componentsPath + "/guide/programs"], returnFirstDependency); define("guide-settings-dialog", [componentsPath + "/guide/guide-settings"], returnFirstDependency); define("loadingDialog", [componentsPath + "/loadingdialog/loadingdialog"], returnFirstDependency); - define("viewManager", [componentsPath + "/viewmanager/viewmanager"], function (viewManager) { + define("viewManager", [componentsPath + "/viewManager/viewManager"], function (viewManager) { window.ViewManager = viewManager; viewManager.dispatchPageEvents(true); return viewManager; From a03502646c0970b9a637853ae6cd050831be3ddf Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Wed, 27 Feb 2019 23:26:28 +0000 Subject: [PATCH 175/220] bug fixes for headroom --- src/components/emby-scroller/emby-scroller.js | 3 +- src/components/headroom/headroom.js | 109 +++++++++--------- src/scripts/librarymenu.js | 3 +- src/scripts/site.js | 1 - 4 files changed, 56 insertions(+), 60 deletions(-) diff --git a/src/components/emby-scroller/emby-scroller.js b/src/components/emby-scroller/emby-scroller.js index d3718cedf3..7ef39eea0a 100644 --- a/src/components/emby-scroller/emby-scroller.js +++ b/src/components/emby-scroller/emby-scroller.js @@ -108,8 +108,7 @@ define(['scroller', 'dom', 'layoutManager', 'inputManager', 'focusManager', 'bro var headroom = new Headroom([], { scroller: elem }); - // initialise - headroom.init(); + headroom.add(document.querySelector('.skinHeader')); elem.headroom = headroom; }); diff --git a/src/components/headroom/headroom.js b/src/components/headroom/headroom.js index 9cb1cac04d..a3cc5b0435 100644 --- a/src/components/headroom/headroom.js +++ b/src/components/headroom/headroom.js @@ -75,47 +75,25 @@ define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, lay this.pinnedClass = options.pinnedClass; this.state = 'clear'; - } - function onScroll() { + this.options = { + offset: 0, + scroller: window, + initialClass: 'headroom', + unPinnedClass: 'headroom--unpinned', + pinnedClass: 'headroom--pinned' + }; - if (this.paused) { - return; - } - - requestAnimationFrame(this.rafCallback || (this.rafCallback = this.update.bind(this))); - } - - Headroom.prototype = { - constructor: Headroom, - - /** - * Initialises the widget - */ - init: function () { - - if (browser.supportsCssAnimation()) { - for (var i = 0, length = this.elems.length; i < length; i++) { - this.elems[i].classList.add(this.initialClass); - this.elems[i].addEventListener('clearheadroom', onHeadroomClearedExternally.bind(this)); - } - - this.attachEvent(); - } - - return this; - }, - - add: function (elem) { + this.add = function (elem) { if (browser.supportsCssAnimation()) { elem.classList.add(this.initialClass); elem.addEventListener('clearheadroom', onHeadroomClearedExternally.bind(this)); this.elems.push(elem); } - }, + }; - remove: function (elem) { + this.remove = function (elem) { elem.classList.remove(this.unPinnedClass); elem.classList.remove(this.initialClass); @@ -125,20 +103,20 @@ define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, lay if (i !== -1) { this.elems.splice(i, 1); } - }, + }; - pause: function () { + this.pause = function () { this.paused = true; - }, + }; - resume: function () { + this.resume = function () { this.paused = false; - }, + }; /** * Unattaches events and removes any classes that were added */ - destroy: function () { + this.destroy = function () { this.initialised = false; @@ -157,13 +135,13 @@ define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, lay capture: false, passive: true }); - }, + }; /** * Attaches the scroll event * @private */ - attachEvent: function () { + this.attachEvent = function () { if (!this.initialised) { this.lastKnownScrollY = this.getScrollY(); this.initialised = true; @@ -177,12 +155,12 @@ define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, lay this.update(); } - }, + }; /** * Unpins the header if it's currently pinned */ - clear: function () { + this.clear = function () { if (this.state === 'clear') { return; @@ -199,12 +177,12 @@ define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, lay classList.remove(unpinnedClass); //classList.remove(pinnedClass); } - }, + }; /** * Unpins the header if it's currently pinned */ - pin: function () { + this.pin = function () { if (this.state === 'pin') { return; @@ -221,12 +199,12 @@ define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, lay classList.remove(unpinnedClass); classList.add(pinnedClass); } - }, + }; /** * Unpins the header if it's currently pinned */ - unpin: function () { + this.unpin = function () { if (this.state === 'unpin') { return; @@ -243,14 +221,14 @@ define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, lay classList.add(unpinnedClass); //classList.remove(pinnedClass); } - }, + }; /** * Gets the Y scroll position * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY * @return {Number} pixels the page has scrolled along the Y-axis */ - getScrollY: function () { + this.getScrollY = function () { var scroller = this.scroller; @@ -269,36 +247,36 @@ define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, lay } return (document.documentElement || document.body).scrollTop; - }, + }; /** * determine if it is appropriate to unpin * @param {int} currentScrollY the current y scroll position * @return {bool} true if should unpin, false otherwise */ - shouldUnpin: function (currentScrollY) { + this.shouldUnpin = function (currentScrollY) { var scrollingDown = currentScrollY > this.lastKnownScrollY, pastOffset = currentScrollY >= this.offset; return scrollingDown && pastOffset; - }, + }; /** * determine if it is appropriate to pin * @param {int} currentScrollY the current y scroll position * @return {bool} true if should pin, false otherwise */ - shouldPin: function (currentScrollY) { + this.shouldPin = function (currentScrollY) { var scrollingUp = currentScrollY < this.lastKnownScrollY, pastOffset = currentScrollY <= this.offset; return scrollingUp || pastOffset; - }, + }; /** * Handles updating the state of the widget */ - update: function () { + this.update = function () { if (this.paused) { return; @@ -330,8 +308,28 @@ define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, lay } this.lastKnownScrollY = currentScrollY; + }; + + + if (browser.supportsCssAnimation()) { + for (var i = 0, length = this.elems.length; i < length; i++) { + this.elems[i].classList.add(this.initialClass); + this.elems[i].addEventListener('clearheadroom', onHeadroomClearedExternally.bind(this)); + } + + this.attachEvent(); } - }; + } + + function onScroll() { + + if (this.paused) { + return; + } + + requestAnimationFrame(this.rafCallback || (this.rafCallback = this.update.bind(this))); + } + /** * Default options * @type {Object} @@ -345,5 +343,4 @@ define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, lay }; return Headroom; - }); \ No newline at end of file diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index 8ade3edb88..9f21b81c16 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -724,7 +724,8 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " } function initHeadRoom(elem) { - require(["headroom"], function (headroom) { + require(["headroom"], function (Headroom) { + var headroom = new Headroom([], {}); headroom.add(elem); }); } diff --git a/src/scripts/site.js b/src/scripts/site.js index cfd2d58f55..1cd32d5273 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -345,7 +345,6 @@ var AppInfo = {}; function createWindowHeadroom(Headroom) { var headroom = new Headroom([], {}); - headroom.init(); return headroom; } From 578a1670f44c06ee618f94ed7349b99895dcc338 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Wed, 27 Feb 2019 23:29:13 +0000 Subject: [PATCH 176/220] module resoltion for viewContainer --- src/components/{viewcontainer-lite.js => viewContainer.js} | 2 +- .../viewmanager/{viewcontainer-lite.css => viewContainer.css} | 0 src/scripts/site.js | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename src/components/{viewcontainer-lite.js => viewContainer.js} (98%) rename src/components/viewmanager/{viewcontainer-lite.css => viewContainer.css} (100%) diff --git a/src/components/viewcontainer-lite.js b/src/components/viewContainer.js similarity index 98% rename from src/components/viewcontainer-lite.js rename to src/components/viewContainer.js index fbcc2754e0..7dd036bc96 100644 --- a/src/components/viewcontainer-lite.js +++ b/src/components/viewContainer.js @@ -1,4 +1,4 @@ -define(["browser", "dom", "layoutManager", "css!components/viewmanager/viewcontainer-lite"], function(browser, dom, layoutManager) { +define(["browser", "dom", "layoutManager", "css!components/viewmanager/viewContainer"], function(browser, dom, layoutManager) { "use strict"; function setControllerClass(view, options) { diff --git a/src/components/viewmanager/viewcontainer-lite.css b/src/components/viewmanager/viewContainer.css similarity index 100% rename from src/components/viewmanager/viewcontainer-lite.css rename to src/components/viewmanager/viewContainer.css diff --git a/src/scripts/site.js b/src/scripts/site.js index 1cd32d5273..dc3c7bfcf3 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -859,7 +859,7 @@ var AppInfo = {}; define("imageUploader", [componentsPath + "/imageuploader/imageuploader"], returnFirstDependency); define("navdrawer", ["components/navdrawer/navdrawer"], returnFirstDependency); define("htmlMediaHelper", [componentsPath + "/htmlvideoplayer/htmlmediahelper"], returnFirstDependency); - define("viewcontainer", ["components/viewcontainer-lite"], returnFirstDependency); + define("viewcontainer", ["components/viewContainer"], returnFirstDependency); define("queryString", [bowerPath + "/query-string/index"], function () { return queryString; }); From ba89941fce474933cf259c1b04bf6dbf8ed229df Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Thu, 28 Feb 2019 00:01:07 +0000 Subject: [PATCH 177/220] module resolution for toast and serverRestartDialog --- .../serverrestartdialog.js => serverRestartDialog.js} | 0 src/components/toast/package.json | 3 +++ src/scripts/site.js | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) rename src/components/{serverrestartdialog/serverrestartdialog.js => serverRestartDialog.js} (100%) create mode 100644 src/components/toast/package.json diff --git a/src/components/serverrestartdialog/serverrestartdialog.js b/src/components/serverRestartDialog.js similarity index 100% rename from src/components/serverrestartdialog/serverrestartdialog.js rename to src/components/serverRestartDialog.js diff --git a/src/components/toast/package.json b/src/components/toast/package.json new file mode 100644 index 0000000000..2e64841a7f --- /dev/null +++ b/src/components/toast/package.json @@ -0,0 +1,3 @@ +{ + "main": "toast.js" +} \ No newline at end of file diff --git a/src/scripts/site.js b/src/scripts/site.js index dc3c7bfcf3..f8e348b5ab 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -754,7 +754,7 @@ var AppInfo = {}; define("emby-radio", [componentsPath + "/emby-radio/emby-radio"], returnFirstDependency); define("emby-textarea", [componentsPath + "/emby-textarea/emby-textarea"], returnFirstDependency); define("collectionEditor", [componentsPath + "/collectioneditor/collectioneditor"], returnFirstDependency); - define("serverRestartDialog", [componentsPath + "/serverrestartdialog/serverrestartdialog"], returnFirstDependency); + define("serverRestartDialog", [componentsPath + "/serverRestartDialog"], returnFirstDependency); define("playlistEditor", [componentsPath + "/playlisteditor/playlisteditor"], returnFirstDependency); define("recordingCreator", [componentsPath + "/recordingcreator/recordingcreator"], returnFirstDependency); define("recordingEditor", [componentsPath + "/recordingcreator/recordingeditor"], returnFirstDependency); From d57629d90f1ddfcf31ad402a91817e4bee3a1b5e Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Thu, 28 Feb 2019 00:06:23 +0000 Subject: [PATCH 178/220] module resolution for serverNotifications --- src/components/apiInput/package.json | 3 --- .../{apiInput => serverNotifications}/gamepadtokey.js | 0 .../{apiInput => serverNotifications}/mouseManager.js | 0 src/components/serverNotifications/package.json | 3 +++ .../serverNotifications.js} | 4 ++-- src/scripts/site.js | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 src/components/apiInput/package.json rename src/components/{apiInput => serverNotifications}/gamepadtokey.js (100%) rename src/components/{apiInput => serverNotifications}/mouseManager.js (100%) create mode 100644 src/components/serverNotifications/package.json rename src/components/{apiInput/apiInput.js => serverNotifications/serverNotifications.js} (98%) diff --git a/src/components/apiInput/package.json b/src/components/apiInput/package.json deleted file mode 100644 index 6c542951b2..0000000000 --- a/src/components/apiInput/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "main": "apiInput.js" -} \ No newline at end of file diff --git a/src/components/apiInput/gamepadtokey.js b/src/components/serverNotifications/gamepadtokey.js similarity index 100% rename from src/components/apiInput/gamepadtokey.js rename to src/components/serverNotifications/gamepadtokey.js diff --git a/src/components/apiInput/mouseManager.js b/src/components/serverNotifications/mouseManager.js similarity index 100% rename from src/components/apiInput/mouseManager.js rename to src/components/serverNotifications/mouseManager.js diff --git a/src/components/serverNotifications/package.json b/src/components/serverNotifications/package.json new file mode 100644 index 0000000000..779da202d2 --- /dev/null +++ b/src/components/serverNotifications/package.json @@ -0,0 +1,3 @@ +{ + "main": "serverNotifications.js" +} \ No newline at end of file diff --git a/src/components/apiInput/apiInput.js b/src/components/serverNotifications/serverNotifications.js similarity index 98% rename from src/components/apiInput/apiInput.js rename to src/components/serverNotifications/serverNotifications.js index 388fb11beb..2537723b68 100644 --- a/src/components/apiInput/apiInput.js +++ b/src/components/serverNotifications/serverNotifications.js @@ -248,10 +248,10 @@ define(['connectionManager', 'playbackManager', 'events', 'inputManager', 'focus }); if (!enableNativeGamepadKeyMapping() && isGamepadSupported()) { - require(["components/apiInput/gamepadtokey"]); + require(["components/serverNotifications/gamepadtokey"]); } - require(["components/apiInput/mouseManager"]); + require(["components/serverNotifications/mouseManager"]); return serverNotifications; }); diff --git a/src/scripts/site.js b/src/scripts/site.js index f8e348b5ab..f4574c36f8 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -873,7 +873,7 @@ var AppInfo = {}; define("fnchecked", ["legacy/fnchecked"], returnFirstDependency); define("dialogHelper", [componentsPath + "/dialogHelper/dialogHelper"], returnFirstDependency); define("inputmanager", ["inputManager"], returnFirstDependency); - define("serverNotifications", [componentsPath + "/apiInput/apiInput"], returnFirstDependency); + define("serverNotifications", [componentsPath + "/serverNotifications/serverNotifications"], returnFirstDependency); define("appFooter-shared", ["appFooter"], createSharedAppFooter); define("skinManager", [componentsPath + "/skinManager"], returnFirstDependency); define("connectionManager", [], function () { From 52af8d487eea5bc50aa82b15411452cafbbfe7ed Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Thu, 28 Feb 2019 00:10:39 +0000 Subject: [PATCH 179/220] module resolution for scroller --- src/components/{scroller/smoothscroller.js => scroller.js} | 0 src/scripts/site.js | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/components/{scroller/smoothscroller.js => scroller.js} (100%) diff --git a/src/components/scroller/smoothscroller.js b/src/components/scroller.js similarity index 100% rename from src/components/scroller/smoothscroller.js rename to src/components/scroller.js diff --git a/src/scripts/site.js b/src/scripts/site.js index f4574c36f8..17a264667b 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -845,7 +845,7 @@ var AppInfo = {}; define("itemrepository", [apiClientBowerPath + "/sync/itemrepository"], returnFirstDependency); define("useractionrepository", [apiClientBowerPath + "/sync/useractionrepository"], returnFirstDependency); define("swiper", [bowerPath + "/Swiper/dist/js/swiper.min", "css!" + bowerPath + "/Swiper/dist/css/swiper.min"], returnFirstDependency); - define("scroller", [componentsPath + "/scroller/smoothscroller"], returnFirstDependency); + define("scroller", [componentsPath + "/scroller"], returnFirstDependency); define("toast", [componentsPath + "/toast/toast"], returnFirstDependency); define("scrollHelper", [componentsPath + "/scrollhelper"], returnFirstDependency); define("touchHelper", [componentsPath + "/touchhelper"], returnFirstDependency); From f56a82b800ac8f705c13b8bb1939882f9ca466c2 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Thu, 28 Feb 2019 00:32:37 +0000 Subject: [PATCH 180/220] module resolution for loading, page and playerSelectionMenu --- src/components/appRouter.js | 2 +- .../loading/{loading-lite.css => loading.css} | 0 .../loading/{loading-lite.js => loading.js} | 6 +- .../{loading-legacy.css => loadingLegacy.css} | 0 .../{loading-legacy.js => loadingLegacy.js} | 2 +- src/components/loading/package.json | 3 + src/components/navdrawer/package.json | 3 + src/{thirdparty/pagejs => components}/page.js | 0 ...yerselection.js => playerSelectionMenu.js} | 0 src/scripts/site.js | 11 +- src/thirdparty/page.js | 1077 +++++++++++++++++ 11 files changed, 1093 insertions(+), 11 deletions(-) rename src/components/loading/{loading-lite.css => loading.css} (100%) rename src/components/loading/{loading-lite.js => loading.js} (93%) rename src/components/loading/{loading-legacy.css => loadingLegacy.css} (100%) rename src/components/loading/{loading-legacy.js => loadingLegacy.js} (90%) create mode 100644 src/components/loading/package.json create mode 100644 src/components/navdrawer/package.json rename src/{thirdparty/pagejs => components}/page.js (100%) rename src/components/playback/{playerselection.js => playerSelectionMenu.js} (100%) create mode 100644 src/thirdparty/page.js diff --git a/src/components/appRouter.js b/src/components/appRouter.js index 92950c66f6..ffe3065bbb 100644 --- a/src/components/appRouter.js +++ b/src/components/appRouter.js @@ -1,4 +1,4 @@ -define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinManager', 'pluginManager', 'backdrop', 'browser', 'pageJs', 'appSettings', 'apphost', 'connectionManager'], function (loading, globalize, events, viewManager, layoutManager, skinManager, pluginManager, backdrop, browser, page, appSettings, appHost, connectionManager) { +define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinManager', 'pluginManager', 'backdrop', 'browser', 'page', 'appSettings', 'apphost', 'connectionManager'], function (loading, globalize, events, viewManager, layoutManager, skinManager, pluginManager, backdrop, browser, page, appSettings, appHost, connectionManager) { 'use strict'; var appRouter = { diff --git a/src/components/loading/loading-lite.css b/src/components/loading/loading.css similarity index 100% rename from src/components/loading/loading-lite.css rename to src/components/loading/loading.css diff --git a/src/components/loading/loading-lite.js b/src/components/loading/loading.js similarity index 93% rename from src/components/loading/loading-lite.js rename to src/components/loading/loading.js index 00aff8f0f8..ad9aea950a 100644 --- a/src/components/loading/loading-lite.js +++ b/src/components/loading/loading.js @@ -1,6 +1,10 @@ -define(['css!./loading-lite'], function () { +define(['components/loading/loadingLegacy', 'browser', 'css!./loading'], function (loadingLegacy, browser) { 'use strict'; + if (browser.tizen || browser.operaTv || browser.chromecast || browser.orsay || browser.web0s || browser.ps4) { + return loadingLegacy; + } + var loadingElem; var layer1; var layer2; diff --git a/src/components/loading/loading-legacy.css b/src/components/loading/loadingLegacy.css similarity index 100% rename from src/components/loading/loading-legacy.css rename to src/components/loading/loadingLegacy.css diff --git a/src/components/loading/loading-legacy.js b/src/components/loading/loadingLegacy.js similarity index 90% rename from src/components/loading/loading-legacy.js rename to src/components/loading/loadingLegacy.js index bb8d8a99ab..c5ffd8dc6b 100644 --- a/src/components/loading/loading-legacy.js +++ b/src/components/loading/loadingLegacy.js @@ -1,4 +1,4 @@ -define(['require', 'css!./loading-legacy'], function (require) { +define(['require', 'css!./loadingLegacy'], function (require) { 'use strict'; var loadingElem; diff --git a/src/components/loading/package.json b/src/components/loading/package.json new file mode 100644 index 0000000000..79fd41b0f8 --- /dev/null +++ b/src/components/loading/package.json @@ -0,0 +1,3 @@ +{ + "main": "loading.js" +} \ No newline at end of file diff --git a/src/components/navdrawer/package.json b/src/components/navdrawer/package.json new file mode 100644 index 0000000000..d02800957b --- /dev/null +++ b/src/components/navdrawer/package.json @@ -0,0 +1,3 @@ +{ + "main": "navdrawer.js" +} \ No newline at end of file diff --git a/src/thirdparty/pagejs/page.js b/src/components/page.js similarity index 100% rename from src/thirdparty/pagejs/page.js rename to src/components/page.js diff --git a/src/components/playback/playerselection.js b/src/components/playback/playerSelectionMenu.js similarity index 100% rename from src/components/playback/playerselection.js rename to src/components/playback/playerSelectionMenu.js diff --git a/src/scripts/site.js b/src/scripts/site.js index 17a264667b..f2c91d0a81 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -445,12 +445,7 @@ var AppInfo = {}; define("prompt", [componentsPath + "/prompt/prompt"], returnFirstDependency); } - if (browser.tizen || browser.operaTv || browser.chromecast || browser.orsay || browser.web0s || browser.ps4) { - define("loading", [componentsPath + "/loading/loading-legacy"], returnFirstDependency); - } else { - define("loading", [componentsPath + "/loading/loading-lite"], returnFirstDependency); - } - + define("loading", [componentsPath + "/loading/loading"], returnFirstDependency); define("multi-download", [componentsPath + "/multidownload"], returnFirstDependency); define("fileDownloader", [componentsPath + "/filedownloader"], returnFirstDependency); define("localassetmanager", [apiClientBowerPath + "/localassetmanager"], returnFirstDependency); @@ -701,7 +696,7 @@ var AppInfo = {}; inputManager: componentsPath + "/inputmanager", qualityoptions: componentsPath + "/qualityoptions", hammer: bowerPath + "/hammerjs/hammer.min", - pageJs: "thirdparty/pagejs/page", + page: "thirdparty/page", focusManager: componentsPath + "/focusmanager", datetime: componentsPath + "/datetime", globalize: componentsPath + "/globalize", @@ -727,7 +722,7 @@ var AppInfo = {}; define("directorybrowser", ["components/directorybrowser/directorybrowser"], returnFirstDependency); define("metadataEditor", [componentsPath + "/metadataeditor/metadataeditor"], returnFirstDependency); define("personEditor", [componentsPath + "/metadataeditor/personeditor"], returnFirstDependency); - define("playerSelectionMenu", [componentsPath + "/playback/playerselection"], returnFirstDependency); + define("playerSelectionMenu", [componentsPath + "/playback/playerSelectionMenu"], returnFirstDependency); define("playerSettingsMenu", [componentsPath + "/playback/playersettingsmenu"], returnFirstDependency); define("playMethodHelper", [componentsPath + "/playback/playmethodhelper"], returnFirstDependency); define("brightnessOsd", [componentsPath + "/playback/brightnessosd"], returnFirstDependency); diff --git a/src/thirdparty/page.js b/src/thirdparty/page.js new file mode 100644 index 0000000000..ce96fd185e --- /dev/null +++ b/src/thirdparty/page.js @@ -0,0 +1,1077 @@ +define([], function () { + + 'use strict'; + + /** + * Detect click event + */ + var clickEvent = ('undefined' !== typeof document) && document.ontouchstart ? 'touchstart' : 'click'; + + /** + * To work properly with the URL + * history.location generated polyfill in https://github.com/devote/HTML5-History-API + */ + + var location = ('undefined' !== typeof window) && (window.history.location || window.location); + + /** + * Perform initial dispatch. + */ + + var dispatch = true; + + + /** + * Decode URL components (query string, pathname, hash). + * Accommodates both regular percent encoding and x-www-form-urlencoded format. + */ + var decodeURLComponents = true; + + /** + * Base path. + */ + + var base = ''; + + /** + * Running flag. + */ + + var running; + + /** + * HashBang option + */ + + var hashbang = false; + + var enableHistory = false; + + /** + * Previous context, for capturing + * page exit events. + */ + + var prevContext; + + var prevPageContext; + + /** + * Register `path` with callback `fn()`, + * or route `path`, or redirection, + * or `page.start()`. + * + * page(fn); + * page('*', fn); + * page('/user/:id', load, user); + * page('/user/' + user.id, { some: 'thing' }); + * page('/user/' + user.id); + * page('/from', '/to') + * page(); + * + * @param {String|Function} path + * @param {Function} fn... + * @api public + */ + + function page(path, fn) { + // + if ('function' === typeof path) { + return page('*', path); + } + + // route to + if ('function' === typeof fn) { + var route = new Route(path); + for (var i = 1; i < arguments.length; ++i) { + page.callbacks.push(route.middleware(arguments[i])); + } + // show with [state] + } else if ('string' === typeof path) { + page['string' === typeof fn ? 'redirect' : 'show'](path, fn); + // start [options] + } else { + page.start(path); + } + } + + /** + * Callback functions. + */ + + page.callbacks = []; + page.exits = []; + + /** + * Current path being processed + * @type {String} + */ + page.current = ''; + + /** + * Number of pages navigated to. + * @type {number} + * + * page.len == 0; + * page('/login'); + * page.len == 1; + */ + + page.len = 0; + + /** + * Get or set basepath to `path`. + * + * @param {String} path + * @api public + */ + + page.base = function (path) { + if (0 === arguments.length) { + return base; + } + base = path; + }; + + /** + * Bind with the given `options`. + * + * Options: + * + * - `click` bind to click events [true] + * - `popstate` bind to popstate [true] + * - `dispatch` perform initial dispatch [true] + * + * @param {Object} options + * @api public + */ + + page.start = function (options) { + options = options || {}; + if (running) { + return; + } + running = true; + if (false === options.dispatch) { + dispatch = false; + } + if (false === options.decodeURLComponents) { + decodeURLComponents = false; + } + if (false !== options.popstate) { + window.addEventListener('popstate', onpopstate, false); + } + if (false !== options.click) { + document.addEventListener(clickEvent, onclick, false); + } + if (options.enableHistory != null) { + enableHistory = options.enableHistory; + } + if (true === options.hashbang) { + hashbang = true; + } + if (!dispatch) { + return; + } + + var url; + + if (hashbang && ~location.hash.indexOf('#!')) { + + url = location.hash.substr(2); + + var href = location.href.toString(); + if (href.indexOf('?') >= href.indexOf('#!')) { + url += location.search; + } + } + else { + url = location.pathname + location.search + location.hash; + } + + page.replace(url, null, true, dispatch); + }; + + /** + * Unbind click and popstate event handlers. + * + * @api public + */ + + page.stop = function () { + if (!running) { + return; + } + page.current = ''; + page.len = 0; + running = false; + document.removeEventListener(clickEvent, onclick, false); + window.removeEventListener('popstate', onpopstate, false); + }; + + /** + * Show `path` with optional `state` object. + * + * @param {String} path + * @param {Object} state + * @param {Boolean} dispatch + * @return {Context} + * @api public + */ + + page.show = function (path, state, dispatch, push, isBack) { + var ctx = new Context(path, state); + ctx.isBack = isBack; + page.current = ctx.path; + if (false !== dispatch) { + page.dispatch(ctx); + } + if (false !== ctx.handled && false !== push) { + ctx.pushState(); + } + return ctx; + }; + + page.restorePreviousState = function () { + + prevContext = prevPageContext; + page.show(prevContext.pathname, prevContext.state, false, true, false); + }; + + /** + * Goes back in the history + * Back should always let the current route push state and then go back. + * + * @param {String} path - fallback path to go back if no more history exists, if undefined defaults to page.base + * @param {Object} [state] + * @api public + */ + + page.back = function (path, state) { + + if (enableHistory) { + // Keep it simple and mimic browser back + history.back(); + return; + } + + if (page.len > 0) { + // this may need more testing to see if all browsers + // wait for the next tick to go back in history + if (enableHistory) { + history.back(); + } else { + + if (backStack.length > 2) { + backStack.length--; + var previousState = backStack[backStack.length - 1]; + page.show(previousState.path, previousState.state, true, false, true); + } + } + page.len--; + } else if (path) { + setTimeout(function () { + page.show(path, state); + }); + } else { + setTimeout(function () { + page.show(base, state); + }); + } + }; + + page.enableNativeHistory = function () { + return enableHistory; + }; + + page.canGoBack = function () { + if (enableHistory) { + return history.length > 1; + } + return (page.len || 0) > 0; + }; + + /** + * Register route to redirect from one path to other + * or just redirect to another route + * + * @param {String} from - if param 'to' is undefined redirects to 'from' + * @param {String} [to] + * @api public + */ + page.redirect = function (from, to) { + // Define route from a path to another + if ('string' === typeof from && 'string' === typeof to) { + page(from, function (e) { + setTimeout(function () { + page.replace(to); + }, 0); + }); + } + + // Wait for the push state and replace it with another + if ('string' === typeof from && 'undefined' === typeof to) { + setTimeout(function () { + page.replace(from); + }, 0); + } + }; + + /** + * Replace `path` with optional `state` object. + * + * @param {String} path + * @param {Object} state + * @return {Context} + * @api public + */ + + + page.replace = function (path, state, init, dispatch, isBack) { + var ctx = new Context(path, state); + ctx.isBack = isBack; + page.current = ctx.path; + ctx.init = init; + ctx.save(); // save before dispatching, which may redirect + if (false !== dispatch) { + page.dispatch(ctx); + } + return ctx; + }; + + /** + * Dispatch the given `ctx`. + * + * @param {Object} ctx + * @api private + */ + + page.dispatch = function (ctx) { + var prev = prevContext, + i = 0, + j = 0; + + prevPageContext = prevContext; + prevContext = ctx; + + function nextExit() { + var fn = page.exits[j++]; + if (!fn) { + return nextEnter(); + } + fn(prev, nextExit); + } + + function nextEnter() { + var fn = page.callbacks[i++]; + + if (ctx.path !== page.current) { + ctx.handled = false; + return; + } + if (!fn) { + return unhandled(ctx); + } + fn(ctx, nextEnter); + } + + if (prev) { + nextExit(); + } else { + nextEnter(); + } + }; + + /** + * Unhandled `ctx`. When it's not the initial + * popstate then redirect. If you wish to handle + * 404s on your own use `page('*', callback)`. + * + * @param {Context} ctx + * @api private + */ + + function unhandled(ctx) { + if (ctx.handled) { + return; + } + var current; + + if (hashbang) { + current = base + location.hash.replace('#!', ''); + } else { + current = location.pathname + location.search; + } + + if (current === ctx.canonicalPath) { + return; + } + page.stop(); + ctx.handled = false; + location.href = ctx.canonicalPath; + } + + /** + * Register an exit route on `path` with + * callback `fn()`, which will be called + * on the previous context when a new + * page is visited. + */ + page.exit = function (path, fn) { + if (typeof path === 'function') { + return page.exit('*', path); + } + + var route = new Route(path); + for (var i = 1; i < arguments.length; ++i) { + page.exits.push(route.middleware(arguments[i])); + } + }; + + /** + * Remove URL encoding from the given `str`. + * Accommodates whitespace in both x-www-form-urlencoded + * and regular percent-encoded form. + * + * @param {str} URL component to decode + */ + function decodeURLEncodedURIComponent(val) { + if (typeof val !== 'string') { return val; } + return decodeURLComponents ? decodeURIComponent(val.replace(/\+/g, ' ')) : val; + } + + /** + * Initialize a new "request" `Context` + * with the given `path` and optional initial `state`. + * + * @param {String} path + * @param {Object} state + * @api public + */ + + function Context(path, state) { + if ('/' === path[0] && 0 !== path.indexOf(base)) { + path = base + (hashbang ? '#!' : '') + path; + } + var i = path.indexOf('?'); + + this.canonicalPath = path; + this.path = path.replace(base, '') || '/'; + if (hashbang) { + this.path = this.path.replace('#!', '') || '/'; + } + + this.title = document.title; + this.state = state || {}; + this.state.path = path; + this.querystring = ~i ? decodeURLEncodedURIComponent(path.slice(i + 1)) : ''; + this.pathname = decodeURLEncodedURIComponent(~i ? path.slice(0, i) : path); + this.params = {}; + + // fragment + this.hash = ''; + if (!hashbang) { + if (!~this.path.indexOf('#')) { + return; + } + var parts = this.path.split('#'); + this.path = parts[0]; + this.hash = decodeURLEncodedURIComponent(parts[1]) || ''; + this.querystring = this.querystring.split('#')[0]; + } + } + + /** + * Expose `Context`. + */ + + page.Context = Context; + var backStack = []; + + /** + * Push state. + * + * @api private + */ + + Context.prototype.pushState = function () { + page.len++; + + if (enableHistory) { + history.pushState(this.state, this.title, hashbang && this.path !== '/' ? '#!' + this.path : this.canonicalPath); + } else { + backStack.push({ + state: this.state, + title: this.title, + url: (hashbang && this.path !== '/' ? '#!' + this.path : this.canonicalPath), + path: this.path + }); + } + }; + + /** + * Save the context state. + * + * @api public + */ + + Context.prototype.save = function () { + + if (enableHistory) { + history.replaceState(this.state, this.title, hashbang && this.path !== '/' ? '#!' + this.path : this.canonicalPath); + } else { + backStack[page.len || 0] = { + state: this.state, + title: this.title, + url: (hashbang && this.path !== '/' ? '#!' + this.path : this.canonicalPath), + path: this.path + }; + } + }; + + /** + * Initialize `Route` with the given HTTP `path`, + * and an array of `callbacks` and `options`. + * + * Options: + * + * - `sensitive` enable case-sensitive routes + * - `strict` enable strict matching for trailing slashes + * + * @param {String} path + * @param {Object} options. + * @api private + */ + + function Route(path, options) { + options = options || {}; + this.path = (path === '*') ? '(.*)' : path; + this.method = 'GET'; + this.regexp = pathToRegexp(this.path, + this.keys = [], + options.sensitive, + options.strict); + } + + /** + * Expose `Route`. + */ + + page.Route = Route; + + /** + * Return route middleware with + * the given callback `fn()`. + * + * @param {Function} fn + * @return {Function} + * @api public + */ + + Route.prototype.middleware = function (fn) { + var self = this; + return function (ctx, next) { + if (self.match(ctx.path, ctx.params)) { + return fn(ctx, next); + } + next(); + }; + }; + + /** + * Check if this route matches `path`, if so + * populate `params`. + * + * @param {String} path + * @param {Object} params + * @return {Boolean} + * @api private + */ + + Route.prototype.match = function (path, params) { + var keys = this.keys, + qsIndex = path.indexOf('?'), + pathname = ~qsIndex ? path.slice(0, qsIndex) : path, + m = this.regexp.exec(decodeURIComponent(pathname)); + + if (!m) { + return false; + } + + for (var i = 1, len = m.length; i < len; ++i) { + var key = keys[i - 1]; + var val = decodeURLEncodedURIComponent(m[i]); + if (val !== undefined || !(hasOwnProperty.call(params, key.name))) { + params[key.name] = val; + } + } + + return true; + }; + + + var previousPopState = {}; + + function ignorePopState(event) { + + var state = event.state || {}; + + if (previousPopState.navigate === false) { + // Ignore + previousPopState = state; + return true; + } + + previousPopState = state; + return false; + } + + page.pushState = function (state, title, url) { + + if (hashbang) { + url = '#!' + url; + } + + history.pushState(state, title, url); + previousPopState = state; + }; + + /** + * Handle "populate" events. + */ + + var onpopstate = (function () { + var loaded = false; + if ('undefined' === typeof window) { + return; + } + if (document.readyState === 'complete') { + loaded = true; + } else { + window.addEventListener('load', function () { + setTimeout(function () { + loaded = true; + }, 0); + }); + } + return function onpopstate(e) { + if (!loaded) { + return; + } + if (ignorePopState(e)) { + return; + } + if (e.state) { + var path = e.state.path; + page.replace(path, e.state, null, null, true); + } else { + page.show(location.pathname + location.hash, undefined, undefined, false, true); + } + }; + })(); + /** + * Handle "click" events. + */ + + function onclick(e, checkWhich) { + + if (1 !== which(e) && checkWhich !== false) { + return; + } + + if (e.metaKey || e.ctrlKey || e.shiftKey) { + return; + } + if (e.defaultPrevented) { + return; + } + + + // ensure link + var el = e.target; + + while (el && 'A' !== el.nodeName) { + el = el.parentNode; + } + if (!el || 'A' !== el.nodeName) { + return; + } + + + // Ignore if tag has + // 1. "download" attribute + // 2. rel="external" attribute + if (el.hasAttribute('download') || el.getAttribute('rel') === 'external') { + return; + } + + // ensure non-hash for the same path + var link = el.getAttribute('href'); + if (link === '#') { + e.preventDefault(); + return; + } + + if (!hashbang && el.pathname === location.pathname && (el.hash || '#' === link)) { + return; + } + + // check target + if (el.target) { + return; + } + + // x-origin + if (!sameOrigin(el.href)) { + return; + } + + // rebuild path + var path = el.pathname + el.search + (el.hash || ''); + + // same page + var orig = path; + + if (path.indexOf(base) === 0) { + path = path.substr(base.length); + } + + if (hashbang) { + path = path.replace('#!', ''); + } + + if (base && orig === path) { + // This is causing navigation to be canceled in edge uwp + // If needed this can be changed to only be skipped when called via handleAnchorClick + //return; + } + + e.preventDefault(); + page.show(orig); + } + + page.handleAnchorClick = onclick; + + /** + * Event button. + */ + + function which(e) { + e = e || window.event; + return null === e.which ? e.button : e.which; + } + + /** + * Check if `href` is the same origin. + */ + + function sameOrigin(href) { + var origin = location.protocol + '//' + location.hostname; + if (location.port) { + origin += ':' + location.port; + } + return (href && (0 === href.indexOf(origin))); + } + + page.sameOrigin = sameOrigin; + + /** + * The main path matching regexp utility. + * + * @type {RegExp} + */ + var PATH_REGEXP = new RegExp([ + // Match escaped characters that would otherwise appear in future matches. + // This allows the user to escape special characters that won't transform. + '(\\\\.)', + // Match Express-style parameters and un-named parameters with a prefix + // and optional suffixes. Matches appear as: + // + // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined] + // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined] + // "/*" => ["/", undefined, undefined, undefined, undefined, "*"] + '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^()])+)\\))?|\\(((?:\\\\.|[^()])+)\\))([+*?])?|(\\*))' + ].join('|'), 'g'); + + /** + * Parse a string for the raw tokens. + * + * @param {String} str + * @return {Array} + */ + function parse(str) { + var tokens = []; + var key = 0; + var index = 0; + var path = ''; + var res; + + while ((res = PATH_REGEXP.exec(str)) != null) { + var m = res[0]; + var escaped = res[1]; + var offset = res.index; + path += str.slice(index, offset); + index = offset + m.length; + + // Ignore already escaped sequences. + if (escaped) { + path += escaped[1]; + continue; + } + + // Push the current path onto the tokens. + if (path) { + tokens.push(path); + path = ''; + } + + var prefix = res[2]; + var name = res[3]; + var capture = res[4]; + var group = res[5]; + var suffix = res[6]; + var asterisk = res[7]; + + var repeat = suffix === '+' || suffix === '*'; + var optional = suffix === '?' || suffix === '*'; + var delimiter = prefix || '/'; + var pattern = capture || group || (asterisk ? '.*' : '[^' + delimiter + ']+?'); + + tokens.push({ + name: name || key++, + prefix: prefix || '', + delimiter: delimiter, + optional: optional, + repeat: repeat, + pattern: escapeGroup(pattern) + }); + } + + // Match any characters still remaining. + if (index < str.length) { + path += str.substr(index); + } + + // If the path exists, push it onto the end. + if (path) { + tokens.push(path); + } + + return tokens; + } + + var isarray = Array.isArray || function (arr) { + return Object.prototype.toString.call(arr) === '[object Array]'; + }; + + /** + * Escape a regular expression string. + * + * @param {String} str + * @return {String} + */ + function escapeString(str) { + return str.replace(/([.+*?=^!:${}()[\]|\/])/g, '\\$1'); + } + + /** + * Escape the capturing group by escaping special characters and meaning. + * + * @param {String} group + * @return {String} + */ + function escapeGroup(group) { + return group.replace(/([=!:$\/()])/g, '\\$1'); + } + + /** + * Attach the keys as a property of the regexp. + * + * @param {RegExp} re + * @param {Array} keys + * @return {RegExp} + */ + function attachKeys(re, keys) { + re.keys = keys; + return re; + } + + /** + * Get the flags for a regexp from the options. + * + * @param {Object} options + * @return {String} + */ + function flags(options) { + return options.sensitive ? '' : 'i'; + } + + /** + * Pull out keys from a regexp. + * + * @param {RegExp} path + * @param {Array} keys + * @return {RegExp} + */ + function regexpToRegexp(path, keys) { + // Use a negative lookahead to match only capturing groups. + var groups = path.source.match(/\((?!\?)/g); + + if (groups) { + for (var i = 0; i < groups.length; i++) { + keys.push({ + name: i, + prefix: null, + delimiter: null, + optional: false, + repeat: false, + pattern: null + }); + } + } + + return attachKeys(path, keys); + } + + /** + * Transform an array into a regexp. + * + * @param {Array} path + * @param {Array} keys + * @param {Object} options + * @return {RegExp} + */ + function arrayToRegexp(path, keys, options) { + var parts = []; + + for (var i = 0; i < path.length; i++) { + parts.push(pathToRegexp(path[i], keys, options).source); + } + + var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options)); + + return attachKeys(regexp, keys); + } + + /** + * Create a path regexp from string input. + * + * @param {String} path + * @param {Array} keys + * @param {Object} options + * @return {RegExp} + */ + function stringToRegexp(path, keys, options) { + var tokens = parse(path); + var re = tokensToRegExp(tokens, options); + + // Attach keys back to the regexp. + for (var i = 0; i < tokens.length; i++) { + if (typeof tokens[i] !== 'string') { + keys.push(tokens[i]); + } + } + + return attachKeys(re, keys); + } + + /** + * Expose a function for taking tokens and returning a RegExp. + * + * @param {Array} tokens + * @param {Array} keys + * @param {Object} options + * @return {RegExp} + */ + function tokensToRegExp(tokens, options) { + options = options || {}; + + var strict = options.strict; + var end = options.end !== false; + var route = ''; + var lastToken = tokens[tokens.length - 1]; + var endsWithSlash = typeof lastToken === 'string' && /\/$/.test(lastToken); + + // Iterate over the tokens and create our regexp string. + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + + if (typeof token === 'string') { + route += escapeString(token); + } else { + var prefix = escapeString(token.prefix); + var capture = token.pattern; + + if (token.repeat) { + capture += '(?:' + prefix + capture + ')*'; + } + + if (token.optional) { + if (prefix) { + capture = '(?:' + prefix + '(' + capture + '))?'; + } else { + capture = '(' + capture + ')?'; + } + } else { + capture = prefix + '(' + capture + ')'; + } + + route += capture; + } + } + + // In non-strict mode we allow a slash at the end of match. If the path to + // match already ends with a slash, we remove it for consistency. The slash + // is valid at the end of a path match, not in the middle. This is important + // in non-ending mode, where "/test/" shouldn't match "/test//route". + if (!strict) { + route = (endsWithSlash ? route.slice(0, -2) : route) + '(?:\\/(?=$))?'; + } + + if (end) { + route += '$'; + } else { + // In non-ending mode, we need the capturing groups to match as much as + // possible by using a positive lookahead to the end or next path segment. + route += strict && endsWithSlash ? '' : '(?=\\/|$)'; + } + + return new RegExp('^' + route, flags(options)); + } + + /** + * Normalize the given path string, returning a regular expression. + * + * An empty array can be passed in for the keys, which will hold the + * placeholder key descriptions. For example, using `/user/:id`, `keys` will + * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`. + * + * @param {(String|RegExp|Array)} path + * @param {Array} [keys] + * @param {Object} [options] + * @return {RegExp} + */ + function pathToRegexp(path, keys, options) { + keys = keys || []; + + if (!isarray(keys)) { + options = keys; + keys = []; + } else if (!options) { + options = {}; + } + + if (path instanceof RegExp) { + return regexpToRegexp(path, keys, options); + } + + if (isarray(path)) { + return arrayToRegexp(path, keys, options); + } + + return stringToRegexp(path, keys, options); + } + + return page; + +}); \ No newline at end of file From 725340617771ab6f7b44ff5b170e9670dc1c0815 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Thu, 28 Feb 2019 00:36:12 +0000 Subject: [PATCH 181/220] module resolution for images modules --- .../images/{basicimagefetcher.js => imageFetcher.js} | 0 src/components/images/{imagehelper.js => imageLoader.js} | 0 src/scripts/site.js | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename src/components/images/{basicimagefetcher.js => imageFetcher.js} (100%) rename src/components/images/{imagehelper.js => imageLoader.js} (100%) diff --git a/src/components/images/basicimagefetcher.js b/src/components/images/imageFetcher.js similarity index 100% rename from src/components/images/basicimagefetcher.js rename to src/components/images/imageFetcher.js diff --git a/src/components/images/imagehelper.js b/src/components/images/imageLoader.js similarity index 100% rename from src/components/images/imagehelper.js rename to src/components/images/imageLoader.js diff --git a/src/scripts/site.js b/src/scripts/site.js index f2c91d0a81..bb1a1dca84 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -424,7 +424,7 @@ var AppInfo = {}; define("registerElement", [bowerPath + "/document-register-element/build/document-register-element"], returnFirstDependency); } - define("imageFetcher", [componentsPath + "/images/basicimagefetcher"], returnFirstDependency); + define("imageFetcher", [componentsPath + "/images/imageFetcher"], returnFirstDependency); var preferNativeAlerts = browser.tv; @@ -717,7 +717,7 @@ var AppInfo = {}; define("libjass", [bowerPath + "/libjass/libjass.min", "css!" + bowerPath + "/libjass/libjass"], returnFirstDependency); define("tunerPicker", ["components/tunerpicker"], returnFirstDependency); define("mainTabsManager", [componentsPath + "/maintabsmanager"], returnFirstDependency); - define("imageLoader", [componentsPath + "/images/imagehelper"], returnFirstDependency); + define("imageLoader", [componentsPath + "/images/imageLoader"], returnFirstDependency); define("appFooter", [componentsPath + "/appfooter/appfooter"], returnFirstDependency); define("directorybrowser", ["components/directorybrowser/directorybrowser"], returnFirstDependency); define("metadataEditor", [componentsPath + "/metadataeditor/metadataeditor"], returnFirstDependency); From d751ff2c194085233fa7f6197b6c744c1b2a8ab2 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Thu, 28 Feb 2019 00:50:03 +0000 Subject: [PATCH 182/220] module resolution for htmlMediaHelper --- .../{htmlvideoplayer/htmlmediahelper.js => htmlMediaHelper.js} | 0 src/scripts/site.js | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/components/{htmlvideoplayer/htmlmediahelper.js => htmlMediaHelper.js} (100%) diff --git a/src/components/htmlvideoplayer/htmlmediahelper.js b/src/components/htmlMediaHelper.js similarity index 100% rename from src/components/htmlvideoplayer/htmlmediahelper.js rename to src/components/htmlMediaHelper.js diff --git a/src/scripts/site.js b/src/scripts/site.js index bb1a1dca84..42bb9f1587 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -853,7 +853,7 @@ var AppInfo = {}; define("scrollStyles", ["css!" + componentsPath + "/scrollstyles"], returnFirstDependency); define("imageUploader", [componentsPath + "/imageuploader/imageuploader"], returnFirstDependency); define("navdrawer", ["components/navdrawer/navdrawer"], returnFirstDependency); - define("htmlMediaHelper", [componentsPath + "/htmlvideoplayer/htmlmediahelper"], returnFirstDependency); + define("htmlMediaHelper", [componentsPath + "/htmlMediaHelper"], returnFirstDependency); define("viewcontainer", ["components/viewContainer"], returnFirstDependency); define("queryString", [bowerPath + "/query-string/index"], function () { return queryString; From 258cea0b8126e73943e93523f393a2174aa0f13a Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sun, 24 Mar 2019 11:38:51 +0000 Subject: [PATCH 183/220] rename viewmanager to viewManager --- src/components/viewManager/package.json | 3 + src/components/viewManager/viewContainer.css | 69 +++++++ .../viewManager.js} | 0 src/components/viewmanager/viewManager.js | 183 ++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 src/components/viewManager/package.json create mode 100644 src/components/viewManager/viewContainer.css rename src/components/{viewmanager/viewmanager.js => viewManager/viewManager.js} (100%) create mode 100644 src/components/viewmanager/viewManager.js diff --git a/src/components/viewManager/package.json b/src/components/viewManager/package.json new file mode 100644 index 0000000000..819371af71 --- /dev/null +++ b/src/components/viewManager/package.json @@ -0,0 +1,3 @@ +{ + "main": "viewManager.js" +} \ No newline at end of file diff --git a/src/components/viewManager/viewContainer.css b/src/components/viewManager/viewContainer.css new file mode 100644 index 0000000000..edfa101976 --- /dev/null +++ b/src/components/viewManager/viewContainer.css @@ -0,0 +1,69 @@ +.mainAnimatedPage { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + contain: layout style size; + /* Can't use will-change because it causes the alpha picker to move when the page scrolls*/ + /*will-change: transform;*/ +} + +@keyframes view-fadeout { + from { + opacity: 1; + } + + to { + opacity: 0; + } +} +@keyframes view-fadein { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@keyframes view-slideleft { + from { + transform: translate3d(100%, 0, 0); + } + + to { + transform: none; + } +} + +@keyframes view-slideleft-r { + from { + transform: none; + } + + to { + transform: translate3d(-100%, 0, 0); + } +} + +@keyframes view-slideright { + from { + transform: translate3d(-100%, 0, 0); + } + + to { + transform: none; + } +} + +@keyframes view-slideright-r { + from { + transform: none; + } + + to { + transform: translate3d(100%, 0, 0); + } +} \ No newline at end of file diff --git a/src/components/viewmanager/viewmanager.js b/src/components/viewManager/viewManager.js similarity index 100% rename from src/components/viewmanager/viewmanager.js rename to src/components/viewManager/viewManager.js diff --git a/src/components/viewmanager/viewManager.js b/src/components/viewmanager/viewManager.js new file mode 100644 index 0000000000..606c7e98c1 --- /dev/null +++ b/src/components/viewmanager/viewManager.js @@ -0,0 +1,183 @@ +define(['viewcontainer', 'focusManager', 'queryString', 'layoutManager'], function (viewcontainer, focusManager, queryString, layoutManager) { + 'use strict'; + + var currentView; + var dispatchPageEvents; + + viewcontainer.setOnBeforeChange(function (newView, isRestored, options) { + + var lastView = currentView; + if (lastView) { + + var beforeHideResult = dispatchViewEvent(lastView, null, 'viewbeforehide', true); + + if (!beforeHideResult) { + // todo: cancel + } + } + + var eventDetail = getViewEventDetail(newView, options, isRestored); + + if (!newView.initComplete) { + newView.initComplete = true; + + if (options.controllerFactory) { + + // Use controller method + var controller = new options.controllerFactory(newView, eventDetail.detail.params); + } + + if (!options.controllerFactory || dispatchPageEvents) { + dispatchViewEvent(newView, eventDetail, 'viewinit'); + } + } + + dispatchViewEvent(newView, eventDetail, 'viewbeforeshow'); + }); + + function onViewChange(view, options, isRestore) { + + var lastView = currentView; + if (lastView) { + dispatchViewEvent(lastView, null, 'viewhide'); + } + + currentView = view; + + var eventDetail = getViewEventDetail(view, options, isRestore); + + if (!isRestore) { + if (options.autoFocus !== false) { + focusManager.autoFocus(view); + } + } + else if (!layoutManager.mobile) { + if (view.activeElement && document.body.contains(view.activeElement) && focusManager.isCurrentlyFocusable(view.activeElement)) { + focusManager.focus(view.activeElement); + } else { + focusManager.autoFocus(view); + } + } + + view.dispatchEvent(new CustomEvent('viewshow', eventDetail)); + + if (dispatchPageEvents) { + view.dispatchEvent(new CustomEvent('pageshow', eventDetail)); + } + } + + function getProperties(view) { + var props = view.getAttribute('data-properties'); + + if (props) { + return props.split(','); + } + + return []; + } + + function dispatchViewEvent(view, eventInfo, eventName, isCancellable) { + + if (!eventInfo) { + eventInfo = { + detail: { + type: view.getAttribute('data-type'), + properties: getProperties(view) + }, + bubbles: true, + cancelable: isCancellable + }; + } + + eventInfo.cancelable = isCancellable || false; + + var eventResult = view.dispatchEvent(new CustomEvent(eventName, eventInfo)); + + if (dispatchPageEvents) { + eventInfo.cancelable = false; + view.dispatchEvent(new CustomEvent(eventName.replace('view', 'page'), eventInfo)); + } + + return eventResult; + } + + function getViewEventDetail(view, options, isRestore) { + + var url = options.url; + var index = url.indexOf('?'); + var params = index === -1 ? {} : queryString.parse(url.substring(index + 1)); + + return { + detail: { + type: view.getAttribute('data-type'), + properties: getProperties(view), + params: params, + isRestored: isRestore, + state: options.state, + + // The route options + options: options.options || {} + }, + bubbles: true, + cancelable: false + }; + } + + function resetCachedViews() { + // Reset all cached views whenever the skin changes + viewcontainer.reset(); + } + + document.addEventListener('skinunload', resetCachedViews); + + function ViewManager() { + } + + ViewManager.prototype.loadView = function (options) { + + var lastView = currentView; + + // Record the element that has focus + if (lastView) { + lastView.activeElement = document.activeElement; + } + + if (options.cancel) { + return; + } + + viewcontainer.loadView(options).then(function (view) { + + onViewChange(view, options); + }); + }; + + ViewManager.prototype.tryRestoreView = function (options, onViewChanging) { + + if (options.cancel) { + return Promise.reject({ cancelled: true }); + } + + // Record the element that has focus + if (currentView) { + currentView.activeElement = document.activeElement; + } + + return viewcontainer.tryRestoreView(options).then(function (view) { + + onViewChanging(); + onViewChange(view, options, true); + + }); + }; + + ViewManager.prototype.currentView = function () { + return currentView; + }; + + ViewManager.prototype.dispatchPageEvents = function (value) { + dispatchPageEvents = value; + }; + + return new ViewManager(); +}); From 2b9559b4a999c98b1dd5327d79f935caf8a21641 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sun, 24 Mar 2019 11:44:33 +0000 Subject: [PATCH 184/220] resolve typo for viewContainer dep --- src/components/viewContainer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/viewContainer.js b/src/components/viewContainer.js index 7dd036bc96..4c02ba3c6e 100644 --- a/src/components/viewContainer.js +++ b/src/components/viewContainer.js @@ -1,4 +1,4 @@ -define(["browser", "dom", "layoutManager", "css!components/viewmanager/viewContainer"], function(browser, dom, layoutManager) { +define(["browser", "dom", "layoutManager", "css!components/viewManager/viewContainer"], function(browser, dom, layoutManager) { "use strict"; function setControllerClass(view, options) { From f783509e33b1bfa38d8ecaa7c9ac2bb2adb1f46d Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sun, 24 Mar 2019 11:47:48 +0000 Subject: [PATCH 185/220] rename dialoghelper to dialogHelper --- .../dialogHelper.js} | 0 src/components/dialogHelper/dialoghelper.css | 173 +++++++ src/components/dialogHelper/package.json | 3 + src/components/dialoghelper/dialogHelper.js | 486 ++++++++++++++++++ 4 files changed, 662 insertions(+) rename src/components/{dialoghelper/dialoghelper.js => dialogHelper/dialogHelper.js} (100%) create mode 100644 src/components/dialogHelper/dialoghelper.css create mode 100644 src/components/dialogHelper/package.json create mode 100644 src/components/dialoghelper/dialogHelper.js diff --git a/src/components/dialoghelper/dialoghelper.js b/src/components/dialogHelper/dialogHelper.js similarity index 100% rename from src/components/dialoghelper/dialoghelper.js rename to src/components/dialogHelper/dialogHelper.js diff --git a/src/components/dialogHelper/dialoghelper.css b/src/components/dialogHelper/dialoghelper.css new file mode 100644 index 0000000000..2cc20b5ff2 --- /dev/null +++ b/src/components/dialogHelper/dialoghelper.css @@ -0,0 +1,173 @@ +.dialogContainer { + display: flex; + align-items: center; + justify-content: center; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 999999 !important; + contain: strict; + overflow: hidden; + overscroll-behavior: contain; +} + +.dialog { + margin: 0; + border-radius: .2em; + -webkit-font-smoothing: antialiased; + border: 0; + padding: 0; + will-change: transform, opacity; + /* Strict does not work well with actionsheet */ + contain: style paint; + box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.4); +} + +.dialog-fixedSize { + border-radius: 0; + max-height: none; + max-width: none; + contain: layout style paint; +} + +.dialog-fullscreen { + /* Needed due to formDialog style */ + position: fixed !important; + top: 0; + bottom: 0; + left: 0; + right: 0; + margin: 0; + box-shadow: none; +} + +@keyframes scaledown { + from { + opacity: 1; + transform: none; + } + + to { + opacity: 0; + transform: scale(.5); + } +} + +@keyframes scaleup { + from { + transform: scale(.5); + opacity: 0; + } + + to { + transform: none; + opacity: 1; + } +} + +@keyframes fadein { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@keyframes fadeout { + + from { + opacity: 1; + } + + to { + opacity: 0; + } +} + +@keyframes slideup { + from { + opacity: 0; + transform: translate3d(0, 30%, 0); + } + + to { + opacity: 1; + transform: none; + } +} + +@keyframes slidedown { + + from { + opacity: 1; + transform: none; + } + + to { + opacity: 0; + transform: translate3d(0, 20%, 0); + } +} + +@media all and (max-width: 80em), all and (max-height: 45em) { + + .dialog-fixedSize, .dialog-fullscreen-lowres { + position: fixed !important; + top: 0 !important; + bottom: 0 !important; + left: 0 !important; + right: 0 !important; + margin: 0 !important; + box-shadow: none; + } +} + +@media all and (min-width: 80em) and (min-height: 45em) { + + .dialog-medium { + width: 80%; + height: 80%; + } + + .dialog-medium-tall { + width: 80%; + height: 90%; + } + + .dialog-small { + width: 60%; + height: 80%; + } + + .dialog-fullscreen-border { + width: 90%; + height: 90%; + } +} + +.noScroll { + overflow-x: hidden !important; + overflow-y: hidden !important; +} + +.dialogBackdrop { + background-color: #000; + opacity: 0; + position: fixed !important; + top: 0 !important; + bottom: 0 !important; + left: 0 !important; + right: 0 !important; + margin: 0 !important; + z-index: 999999 !important; + transition: opacity ease-out 0.2s; + will-change: opacity; +} + +.dialogBackdropOpened { + opacity: .5; +} diff --git a/src/components/dialogHelper/package.json b/src/components/dialogHelper/package.json new file mode 100644 index 0000000000..71863d045f --- /dev/null +++ b/src/components/dialogHelper/package.json @@ -0,0 +1,3 @@ +{ + "main": "dialogHelper.js" +} \ No newline at end of file diff --git a/src/components/dialoghelper/dialogHelper.js b/src/components/dialoghelper/dialogHelper.js new file mode 100644 index 0000000000..36bb23bfd7 --- /dev/null +++ b/src/components/dialoghelper/dialogHelper.js @@ -0,0 +1,486 @@ +define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', 'dom', 'css!./dialoghelper.css', 'scrollStyles'], function (appRouter, focusManager, browser, layoutManager, inputManager, dom) { + 'use strict'; + + var globalOnOpenCallback; + + function enableAnimation() { + + // too slow + if (browser.tv) { + return false; + } + + return browser.supportsCssAnimation(); + } + + function removeCenterFocus(dlg) { + + if (layoutManager.tv) { + if (dlg.classList.contains('scrollX')) { + centerFocus(dlg, true, false); + } + else if (dlg.classList.contains('smoothScrollY')) { + centerFocus(dlg, false, false); + } + } + } + + function tryRemoveElement(elem) { + var parentNode = elem.parentNode; + if (parentNode) { + + // Seeing crashes in edge webview + try { + parentNode.removeChild(elem); + } catch (err) { + console.log('Error removing dialog element: ' + err); + } + } + } + + function DialogHashHandler(dlg, hash, resolve) { + + var self = this; + self.originalUrl = window.location.href; + var activeElement = document.activeElement; + var removeScrollLockOnClose = false; + + function onHashChange(e) { + + var isBack = self.originalUrl === window.location.href; + + if (isBack || !isOpened(dlg)) { + window.removeEventListener('popstate', onHashChange); + } + + if (isBack) { + self.closedByBack = true; + closeDialog(dlg); + } + } + + function onBackCommand(e) { + + if (e.detail.command === 'back') { + self.closedByBack = true; + e.preventDefault(); + e.stopPropagation(); + closeDialog(dlg); + } + } + + function onDialogClosed() { + + if (!isHistoryEnabled(dlg)) { + inputManager.off(dlg, onBackCommand); + } + + window.removeEventListener('popstate', onHashChange); + + removeBackdrop(dlg); + dlg.classList.remove('opened'); + + if (removeScrollLockOnClose) { + document.body.classList.remove('noScroll'); + } + + if (!self.closedByBack && isHistoryEnabled(dlg)) { + var state = history.state || {}; + if (state.dialogId === hash) { + history.back(); + } + } + + if (layoutManager.tv) { + focusManager.focus(activeElement); + } + + if (dlg.getAttribute('data-removeonclose') !== 'false') { + removeCenterFocus(dlg); + + var dialogContainer = dlg.dialogContainer; + if (dialogContainer) { + tryRemoveElement(dialogContainer); + dlg.dialogContainer = null; + } else { + tryRemoveElement(dlg); + } + } + + //resolve(); + // if we just called history.back(), then use a timeout to allow the history events to fire first + setTimeout(function () { + resolve({ + element: dlg, + closedByBack: self.closedByBack + }); + }, 1); + } + + dlg.addEventListener('close', onDialogClosed); + + var center = !dlg.classList.contains('dialog-fixedSize'); + if (center) { + dlg.classList.add('centeredDialog'); + } + + dlg.classList.remove('hide'); + + addBackdropOverlay(dlg); + + dlg.classList.add('opened'); + dlg.dispatchEvent(new CustomEvent('open', { + bubbles: false, + cancelable: false + })); + + if (dlg.getAttribute('data-lockscroll') === 'true' && !document.body.classList.contains('noScroll')) { + document.body.classList.add('noScroll'); + removeScrollLockOnClose = true; + } + + animateDialogOpen(dlg); + + if (isHistoryEnabled(dlg)) { + appRouter.pushState({ dialogId: hash }, "Dialog", '#' + hash); + + window.addEventListener('popstate', onHashChange); + } else { + inputManager.on(dlg, onBackCommand); + } + } + + function addBackdropOverlay(dlg) { + + var backdrop = document.createElement('div'); + backdrop.classList.add('dialogBackdrop'); + + var backdropParent = dlg.dialogContainer || dlg; + backdropParent.parentNode.insertBefore(backdrop, backdropParent); + dlg.backdrop = backdrop; + + // trigger reflow or the backdrop will not animate + void backdrop.offsetWidth; + backdrop.classList.add('dialogBackdropOpened'); + + dom.addEventListener((dlg.dialogContainer || backdrop), 'click', function (e) { + if (e.target === dlg.dialogContainer) { + close(dlg); + } + }, { + passive: true + }); + } + + function isHistoryEnabled(dlg) { + return dlg.getAttribute('data-history') === 'true'; + } + + function open(dlg) { + + if (globalOnOpenCallback) { + globalOnOpenCallback(dlg); + } + + var parent = dlg.parentNode; + if (parent) { + parent.removeChild(dlg); + } + + var dialogContainer = document.createElement('div'); + dialogContainer.classList.add('dialogContainer'); + dialogContainer.appendChild(dlg); + dlg.dialogContainer = dialogContainer; + document.body.appendChild(dialogContainer); + + return new Promise(function (resolve, reject) { + + new DialogHashHandler(dlg, 'dlg' + new Date().getTime(), resolve); + }); + } + + function isOpened(dlg) { + + //return dlg.opened; + return !dlg.classList.contains('hide'); + } + + function close(dlg) { + + if (isOpened(dlg)) { + if (isHistoryEnabled(dlg)) { + history.back(); + } else { + closeDialog(dlg); + } + } + } + + function closeDialog(dlg) { + + if (!dlg.classList.contains('hide')) { + + dlg.dispatchEvent(new CustomEvent('closing', { + bubbles: false, + cancelable: false + })); + + var onAnimationFinish = function () { + focusManager.popScope(dlg); + + dlg.classList.add('hide'); + dlg.dispatchEvent(new CustomEvent('close', { + bubbles: false, + cancelable: false + })); + }; + + animateDialogClose(dlg, onAnimationFinish); + } + } + + function animateDialogOpen(dlg) { + + var onAnimationFinish = function () { + focusManager.pushScope(dlg); + if (dlg.getAttribute('data-autofocus') === 'true') { + focusManager.autoFocus(dlg); + } + }; + + if (enableAnimation()) { + + var onFinish = function () { + dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, { + once: true + }); + onAnimationFinish(); + }; + dom.addEventListener(dlg, dom.whichAnimationEvent(), onFinish, { + once: true + }); + return; + } + + onAnimationFinish(); + } + + function animateDialogClose(dlg, onAnimationFinish) { + + if (enableAnimation()) { + + var animated = true; + + switch (dlg.animationConfig.exit.name) { + + case 'fadeout': + dlg.style.animation = 'fadeout ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both'; + break; + case 'scaledown': + dlg.style.animation = 'scaledown ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both'; + break; + case 'slidedown': + dlg.style.animation = 'slidedown ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both'; + break; + default: + animated = false; + break; + } + var onFinish = function () { + dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, { + once: true + }); + onAnimationFinish(); + }; + dom.addEventListener(dlg, dom.whichAnimationEvent(), onFinish, { + once: true + }); + + if (animated) { + return; + } + } + + onAnimationFinish(); + } + + var supportsOverscrollBehavior = 'overscroll-behavior-y' in document.body.style; + + function shouldLockDocumentScroll(options) { + + if (supportsOverscrollBehavior && (options.size || !browser.touch)) { + return false; + } + + if (options.lockScroll != null) { + return options.lockScroll; + } + + if (options.size === 'fullscreen') { + return true; + } + + if (options.size) { + return true; + } + + return browser.touch; + } + + function removeBackdrop(dlg) { + + var backdrop = dlg.backdrop; + + if (!backdrop) { + return; + } + + dlg.backdrop = null; + + var onAnimationFinish = function () { + tryRemoveElement(backdrop); + }; + + if (enableAnimation()) { + + backdrop.classList.remove('dialogBackdropOpened'); + + // this is not firing animatonend + setTimeout(onAnimationFinish, 300); + return; + } + + onAnimationFinish(); + } + + function centerFocus(elem, horiz, on) { + require(['scrollHelper'], function (scrollHelper) { + var fn = on ? 'on' : 'off'; + scrollHelper.centerFocus[fn](elem, horiz); + }); + } + + function createDialog(options) { + + options = options || {}; + + // If there's no native dialog support, use a plain div + // Also not working well in samsung tizen browser, content inside not clickable + // Just go ahead and always use a plain div because we're seeing issues overlaying absoltutely positioned content over a modal dialog + var dlg = document.createElement('div'); + + dlg.classList.add('focuscontainer'); + dlg.classList.add('hide'); + + if (shouldLockDocumentScroll(options)) { + dlg.setAttribute('data-lockscroll', 'true'); + } + + if (options.enableHistory !== false && appRouter.enableNativeHistory()) { + dlg.setAttribute('data-history', 'true'); + } + + // without this safari will scroll the background instead of the dialog contents + // but not needed here since this is already on top of an existing dialog + // but skip it in IE because it's causing the entire browser to hang + // Also have to disable for firefox because it's causing select elements to not be clickable + if (options.modal !== false) { + dlg.setAttribute('modal', 'modal'); + } + + if (options.autoFocus !== false) { + dlg.setAttribute('data-autofocus', 'true'); + } + + var defaultEntryAnimation; + var defaultExitAnimation; + + defaultEntryAnimation = 'scaleup'; + defaultExitAnimation = 'scaledown'; + var entryAnimation = options.entryAnimation || defaultEntryAnimation; + var exitAnimation = options.exitAnimation || defaultExitAnimation; + + // If it's not fullscreen then lower the default animation speed to make it open really fast + var entryAnimationDuration = options.entryAnimationDuration || (options.size !== 'fullscreen' ? 180 : 280); + var exitAnimationDuration = options.exitAnimationDuration || (options.size !== 'fullscreen' ? 120 : 220); + + dlg.animationConfig = { + // scale up + 'entry': { + name: entryAnimation, + timing: { + duration: entryAnimationDuration, + easing: 'ease-out' + } + }, + // fade out + 'exit': { + name: exitAnimation, + timing: { + duration: exitAnimationDuration, + easing: 'ease-out', + fill: 'both' + } + } + }; + + dlg.classList.add('dialog'); + + if (options.scrollX) { + dlg.classList.add('scrollX'); + dlg.classList.add('smoothScrollX'); + + if (layoutManager.tv) { + centerFocus(dlg, true, true); + } + } + else if (options.scrollY !== false) { + dlg.classList.add('smoothScrollY'); + + if (layoutManager.tv) { + centerFocus(dlg, false, true); + } + } + + if (options.removeOnClose) { + dlg.setAttribute('data-removeonclose', 'true'); + } + + if (options.size) { + dlg.classList.add('dialog-fixedSize'); + dlg.classList.add('dialog-' + options.size); + } + + if (enableAnimation()) { + + switch (dlg.animationConfig.entry.name) { + + case 'fadein': + dlg.style.animation = 'fadein ' + entryAnimationDuration + 'ms ease-out normal'; + break; + case 'scaleup': + dlg.style.animation = 'scaleup ' + entryAnimationDuration + 'ms ease-out normal both'; + break; + case 'slideup': + dlg.style.animation = 'slideup ' + entryAnimationDuration + 'ms ease-out normal'; + break; + case 'slidedown': + dlg.style.animation = 'slidedown ' + entryAnimationDuration + 'ms ease-out normal'; + break; + default: + break; + } + } + + return dlg; + } + + return { + open: open, + close: close, + createDialog: createDialog, + setOnOpen: function (val) { + globalOnOpenCallback = val; + } + }; +}); \ No newline at end of file From c42ac7e6507110c4ebdfebff85767bea57dc4680 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sun, 24 Mar 2019 11:58:55 +0000 Subject: [PATCH 186/220] remove emby-linkbutton requires --- src/addplugin.html | 2 +- src/useredit.html | 2 +- src/userlibraryaccess.html | 2 +- src/userparentalcontrol.html | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/addplugin.html b/src/addplugin.html index 08c36fb194..38de32c207 100644 --- a/src/addplugin.html +++ b/src/addplugin.html @@ -1,4 +1,4 @@ -
+
diff --git a/src/useredit.html b/src/useredit.html index a8247fa771..9acf162e89 100644 --- a/src/useredit.html +++ b/src/useredit.html @@ -1,4 +1,4 @@ -
+
diff --git a/src/userlibraryaccess.html b/src/userlibraryaccess.html index e267e992a3..cb39571fab 100644 --- a/src/userlibraryaccess.html +++ b/src/userlibraryaccess.html @@ -1,4 +1,4 @@ -
+
diff --git a/src/userparentalcontrol.html b/src/userparentalcontrol.html index 5184de66db..2ac8e01925 100644 --- a/src/userparentalcontrol.html +++ b/src/userparentalcontrol.html @@ -1,4 +1,4 @@ -
+
From ad813701c51a6a131cdef23cbfd9c012825ab3b3 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sun, 24 Mar 2019 12:15:13 +0000 Subject: [PATCH 187/220] fix eslint error for appRouter module --- src/components/appRouter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/appRouter.js b/src/components/appRouter.js index ffe3065bbb..f9761d4d61 100644 --- a/src/components/appRouter.js +++ b/src/components/appRouter.js @@ -410,7 +410,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM if (apiClient && apiClient.isLoggedIn()) { console.log('appRouter - user is authenticated'); - + if (route.isDefaultRoute) { console.log('appRouter - loading skin home page'); loadUserSkinWithOptions(ctx); From b8cdb3d94e1afbed6e758422fb46cfff6cf0c291 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Mon, 25 Mar 2019 22:57:08 +0000 Subject: [PATCH 188/220] removed old dialoghelper --- src/components/dialoghelper/dialogHelper.js | 486 ------------------- src/components/dialoghelper/dialoghelper.css | 173 ------- src/components/dialoghelper/package.json | 3 - 3 files changed, 662 deletions(-) delete mode 100644 src/components/dialoghelper/dialogHelper.js delete mode 100644 src/components/dialoghelper/dialoghelper.css delete mode 100644 src/components/dialoghelper/package.json diff --git a/src/components/dialoghelper/dialogHelper.js b/src/components/dialoghelper/dialogHelper.js deleted file mode 100644 index 36bb23bfd7..0000000000 --- a/src/components/dialoghelper/dialogHelper.js +++ /dev/null @@ -1,486 +0,0 @@ -define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', 'dom', 'css!./dialoghelper.css', 'scrollStyles'], function (appRouter, focusManager, browser, layoutManager, inputManager, dom) { - 'use strict'; - - var globalOnOpenCallback; - - function enableAnimation() { - - // too slow - if (browser.tv) { - return false; - } - - return browser.supportsCssAnimation(); - } - - function removeCenterFocus(dlg) { - - if (layoutManager.tv) { - if (dlg.classList.contains('scrollX')) { - centerFocus(dlg, true, false); - } - else if (dlg.classList.contains('smoothScrollY')) { - centerFocus(dlg, false, false); - } - } - } - - function tryRemoveElement(elem) { - var parentNode = elem.parentNode; - if (parentNode) { - - // Seeing crashes in edge webview - try { - parentNode.removeChild(elem); - } catch (err) { - console.log('Error removing dialog element: ' + err); - } - } - } - - function DialogHashHandler(dlg, hash, resolve) { - - var self = this; - self.originalUrl = window.location.href; - var activeElement = document.activeElement; - var removeScrollLockOnClose = false; - - function onHashChange(e) { - - var isBack = self.originalUrl === window.location.href; - - if (isBack || !isOpened(dlg)) { - window.removeEventListener('popstate', onHashChange); - } - - if (isBack) { - self.closedByBack = true; - closeDialog(dlg); - } - } - - function onBackCommand(e) { - - if (e.detail.command === 'back') { - self.closedByBack = true; - e.preventDefault(); - e.stopPropagation(); - closeDialog(dlg); - } - } - - function onDialogClosed() { - - if (!isHistoryEnabled(dlg)) { - inputManager.off(dlg, onBackCommand); - } - - window.removeEventListener('popstate', onHashChange); - - removeBackdrop(dlg); - dlg.classList.remove('opened'); - - if (removeScrollLockOnClose) { - document.body.classList.remove('noScroll'); - } - - if (!self.closedByBack && isHistoryEnabled(dlg)) { - var state = history.state || {}; - if (state.dialogId === hash) { - history.back(); - } - } - - if (layoutManager.tv) { - focusManager.focus(activeElement); - } - - if (dlg.getAttribute('data-removeonclose') !== 'false') { - removeCenterFocus(dlg); - - var dialogContainer = dlg.dialogContainer; - if (dialogContainer) { - tryRemoveElement(dialogContainer); - dlg.dialogContainer = null; - } else { - tryRemoveElement(dlg); - } - } - - //resolve(); - // if we just called history.back(), then use a timeout to allow the history events to fire first - setTimeout(function () { - resolve({ - element: dlg, - closedByBack: self.closedByBack - }); - }, 1); - } - - dlg.addEventListener('close', onDialogClosed); - - var center = !dlg.classList.contains('dialog-fixedSize'); - if (center) { - dlg.classList.add('centeredDialog'); - } - - dlg.classList.remove('hide'); - - addBackdropOverlay(dlg); - - dlg.classList.add('opened'); - dlg.dispatchEvent(new CustomEvent('open', { - bubbles: false, - cancelable: false - })); - - if (dlg.getAttribute('data-lockscroll') === 'true' && !document.body.classList.contains('noScroll')) { - document.body.classList.add('noScroll'); - removeScrollLockOnClose = true; - } - - animateDialogOpen(dlg); - - if (isHistoryEnabled(dlg)) { - appRouter.pushState({ dialogId: hash }, "Dialog", '#' + hash); - - window.addEventListener('popstate', onHashChange); - } else { - inputManager.on(dlg, onBackCommand); - } - } - - function addBackdropOverlay(dlg) { - - var backdrop = document.createElement('div'); - backdrop.classList.add('dialogBackdrop'); - - var backdropParent = dlg.dialogContainer || dlg; - backdropParent.parentNode.insertBefore(backdrop, backdropParent); - dlg.backdrop = backdrop; - - // trigger reflow or the backdrop will not animate - void backdrop.offsetWidth; - backdrop.classList.add('dialogBackdropOpened'); - - dom.addEventListener((dlg.dialogContainer || backdrop), 'click', function (e) { - if (e.target === dlg.dialogContainer) { - close(dlg); - } - }, { - passive: true - }); - } - - function isHistoryEnabled(dlg) { - return dlg.getAttribute('data-history') === 'true'; - } - - function open(dlg) { - - if (globalOnOpenCallback) { - globalOnOpenCallback(dlg); - } - - var parent = dlg.parentNode; - if (parent) { - parent.removeChild(dlg); - } - - var dialogContainer = document.createElement('div'); - dialogContainer.classList.add('dialogContainer'); - dialogContainer.appendChild(dlg); - dlg.dialogContainer = dialogContainer; - document.body.appendChild(dialogContainer); - - return new Promise(function (resolve, reject) { - - new DialogHashHandler(dlg, 'dlg' + new Date().getTime(), resolve); - }); - } - - function isOpened(dlg) { - - //return dlg.opened; - return !dlg.classList.contains('hide'); - } - - function close(dlg) { - - if (isOpened(dlg)) { - if (isHistoryEnabled(dlg)) { - history.back(); - } else { - closeDialog(dlg); - } - } - } - - function closeDialog(dlg) { - - if (!dlg.classList.contains('hide')) { - - dlg.dispatchEvent(new CustomEvent('closing', { - bubbles: false, - cancelable: false - })); - - var onAnimationFinish = function () { - focusManager.popScope(dlg); - - dlg.classList.add('hide'); - dlg.dispatchEvent(new CustomEvent('close', { - bubbles: false, - cancelable: false - })); - }; - - animateDialogClose(dlg, onAnimationFinish); - } - } - - function animateDialogOpen(dlg) { - - var onAnimationFinish = function () { - focusManager.pushScope(dlg); - if (dlg.getAttribute('data-autofocus') === 'true') { - focusManager.autoFocus(dlg); - } - }; - - if (enableAnimation()) { - - var onFinish = function () { - dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, { - once: true - }); - onAnimationFinish(); - }; - dom.addEventListener(dlg, dom.whichAnimationEvent(), onFinish, { - once: true - }); - return; - } - - onAnimationFinish(); - } - - function animateDialogClose(dlg, onAnimationFinish) { - - if (enableAnimation()) { - - var animated = true; - - switch (dlg.animationConfig.exit.name) { - - case 'fadeout': - dlg.style.animation = 'fadeout ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both'; - break; - case 'scaledown': - dlg.style.animation = 'scaledown ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both'; - break; - case 'slidedown': - dlg.style.animation = 'slidedown ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both'; - break; - default: - animated = false; - break; - } - var onFinish = function () { - dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, { - once: true - }); - onAnimationFinish(); - }; - dom.addEventListener(dlg, dom.whichAnimationEvent(), onFinish, { - once: true - }); - - if (animated) { - return; - } - } - - onAnimationFinish(); - } - - var supportsOverscrollBehavior = 'overscroll-behavior-y' in document.body.style; - - function shouldLockDocumentScroll(options) { - - if (supportsOverscrollBehavior && (options.size || !browser.touch)) { - return false; - } - - if (options.lockScroll != null) { - return options.lockScroll; - } - - if (options.size === 'fullscreen') { - return true; - } - - if (options.size) { - return true; - } - - return browser.touch; - } - - function removeBackdrop(dlg) { - - var backdrop = dlg.backdrop; - - if (!backdrop) { - return; - } - - dlg.backdrop = null; - - var onAnimationFinish = function () { - tryRemoveElement(backdrop); - }; - - if (enableAnimation()) { - - backdrop.classList.remove('dialogBackdropOpened'); - - // this is not firing animatonend - setTimeout(onAnimationFinish, 300); - return; - } - - onAnimationFinish(); - } - - function centerFocus(elem, horiz, on) { - require(['scrollHelper'], function (scrollHelper) { - var fn = on ? 'on' : 'off'; - scrollHelper.centerFocus[fn](elem, horiz); - }); - } - - function createDialog(options) { - - options = options || {}; - - // If there's no native dialog support, use a plain div - // Also not working well in samsung tizen browser, content inside not clickable - // Just go ahead and always use a plain div because we're seeing issues overlaying absoltutely positioned content over a modal dialog - var dlg = document.createElement('div'); - - dlg.classList.add('focuscontainer'); - dlg.classList.add('hide'); - - if (shouldLockDocumentScroll(options)) { - dlg.setAttribute('data-lockscroll', 'true'); - } - - if (options.enableHistory !== false && appRouter.enableNativeHistory()) { - dlg.setAttribute('data-history', 'true'); - } - - // without this safari will scroll the background instead of the dialog contents - // but not needed here since this is already on top of an existing dialog - // but skip it in IE because it's causing the entire browser to hang - // Also have to disable for firefox because it's causing select elements to not be clickable - if (options.modal !== false) { - dlg.setAttribute('modal', 'modal'); - } - - if (options.autoFocus !== false) { - dlg.setAttribute('data-autofocus', 'true'); - } - - var defaultEntryAnimation; - var defaultExitAnimation; - - defaultEntryAnimation = 'scaleup'; - defaultExitAnimation = 'scaledown'; - var entryAnimation = options.entryAnimation || defaultEntryAnimation; - var exitAnimation = options.exitAnimation || defaultExitAnimation; - - // If it's not fullscreen then lower the default animation speed to make it open really fast - var entryAnimationDuration = options.entryAnimationDuration || (options.size !== 'fullscreen' ? 180 : 280); - var exitAnimationDuration = options.exitAnimationDuration || (options.size !== 'fullscreen' ? 120 : 220); - - dlg.animationConfig = { - // scale up - 'entry': { - name: entryAnimation, - timing: { - duration: entryAnimationDuration, - easing: 'ease-out' - } - }, - // fade out - 'exit': { - name: exitAnimation, - timing: { - duration: exitAnimationDuration, - easing: 'ease-out', - fill: 'both' - } - } - }; - - dlg.classList.add('dialog'); - - if (options.scrollX) { - dlg.classList.add('scrollX'); - dlg.classList.add('smoothScrollX'); - - if (layoutManager.tv) { - centerFocus(dlg, true, true); - } - } - else if (options.scrollY !== false) { - dlg.classList.add('smoothScrollY'); - - if (layoutManager.tv) { - centerFocus(dlg, false, true); - } - } - - if (options.removeOnClose) { - dlg.setAttribute('data-removeonclose', 'true'); - } - - if (options.size) { - dlg.classList.add('dialog-fixedSize'); - dlg.classList.add('dialog-' + options.size); - } - - if (enableAnimation()) { - - switch (dlg.animationConfig.entry.name) { - - case 'fadein': - dlg.style.animation = 'fadein ' + entryAnimationDuration + 'ms ease-out normal'; - break; - case 'scaleup': - dlg.style.animation = 'scaleup ' + entryAnimationDuration + 'ms ease-out normal both'; - break; - case 'slideup': - dlg.style.animation = 'slideup ' + entryAnimationDuration + 'ms ease-out normal'; - break; - case 'slidedown': - dlg.style.animation = 'slidedown ' + entryAnimationDuration + 'ms ease-out normal'; - break; - default: - break; - } - } - - return dlg; - } - - return { - open: open, - close: close, - createDialog: createDialog, - setOnOpen: function (val) { - globalOnOpenCallback = val; - } - }; -}); \ No newline at end of file diff --git a/src/components/dialoghelper/dialoghelper.css b/src/components/dialoghelper/dialoghelper.css deleted file mode 100644 index 2cc20b5ff2..0000000000 --- a/src/components/dialoghelper/dialoghelper.css +++ /dev/null @@ -1,173 +0,0 @@ -.dialogContainer { - display: flex; - align-items: center; - justify-content: center; - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 999999 !important; - contain: strict; - overflow: hidden; - overscroll-behavior: contain; -} - -.dialog { - margin: 0; - border-radius: .2em; - -webkit-font-smoothing: antialiased; - border: 0; - padding: 0; - will-change: transform, opacity; - /* Strict does not work well with actionsheet */ - contain: style paint; - box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.4); -} - -.dialog-fixedSize { - border-radius: 0; - max-height: none; - max-width: none; - contain: layout style paint; -} - -.dialog-fullscreen { - /* Needed due to formDialog style */ - position: fixed !important; - top: 0; - bottom: 0; - left: 0; - right: 0; - margin: 0; - box-shadow: none; -} - -@keyframes scaledown { - from { - opacity: 1; - transform: none; - } - - to { - opacity: 0; - transform: scale(.5); - } -} - -@keyframes scaleup { - from { - transform: scale(.5); - opacity: 0; - } - - to { - transform: none; - opacity: 1; - } -} - -@keyframes fadein { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} - -@keyframes fadeout { - - from { - opacity: 1; - } - - to { - opacity: 0; - } -} - -@keyframes slideup { - from { - opacity: 0; - transform: translate3d(0, 30%, 0); - } - - to { - opacity: 1; - transform: none; - } -} - -@keyframes slidedown { - - from { - opacity: 1; - transform: none; - } - - to { - opacity: 0; - transform: translate3d(0, 20%, 0); - } -} - -@media all and (max-width: 80em), all and (max-height: 45em) { - - .dialog-fixedSize, .dialog-fullscreen-lowres { - position: fixed !important; - top: 0 !important; - bottom: 0 !important; - left: 0 !important; - right: 0 !important; - margin: 0 !important; - box-shadow: none; - } -} - -@media all and (min-width: 80em) and (min-height: 45em) { - - .dialog-medium { - width: 80%; - height: 80%; - } - - .dialog-medium-tall { - width: 80%; - height: 90%; - } - - .dialog-small { - width: 60%; - height: 80%; - } - - .dialog-fullscreen-border { - width: 90%; - height: 90%; - } -} - -.noScroll { - overflow-x: hidden !important; - overflow-y: hidden !important; -} - -.dialogBackdrop { - background-color: #000; - opacity: 0; - position: fixed !important; - top: 0 !important; - bottom: 0 !important; - left: 0 !important; - right: 0 !important; - margin: 0 !important; - z-index: 999999 !important; - transition: opacity ease-out 0.2s; - will-change: opacity; -} - -.dialogBackdropOpened { - opacity: .5; -} diff --git a/src/components/dialoghelper/package.json b/src/components/dialoghelper/package.json deleted file mode 100644 index 71863d045f..0000000000 --- a/src/components/dialoghelper/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "main": "dialogHelper.js" -} \ No newline at end of file From 4013ac8c8fce0ef1c42bbc0538bed109d65f4edb Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Mon, 25 Mar 2019 23:02:39 +0000 Subject: [PATCH 189/220] removed duplicate emby-button module as dependency --- src/components/collectioneditor/collectioneditor.js | 2 +- src/components/directorybrowser/directorybrowser.js | 2 +- src/components/filtermenu/filtermenu.js | 2 +- src/components/homesections/homesections.js | 2 +- src/components/imagedownloader/imagedownloader.js | 4 ++-- src/components/maintabsmanager.js | 2 +- src/components/sortmenu/sortmenu.js | 2 +- src/components/viewsettings/viewsettings.js | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/collectioneditor/collectioneditor.js b/src/components/collectioneditor/collectioneditor.js index 8c14405330..5c1bd5c6f8 100644 --- a/src/components/collectioneditor/collectioneditor.js +++ b/src/components/collectioneditor/collectioneditor.js @@ -1,4 +1,4 @@ -define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'emby-button', 'flexStyles'], function (dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize) { +define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize) { 'use strict'; var currentServerId; diff --git a/src/components/directorybrowser/directorybrowser.js b/src/components/directorybrowser/directorybrowser.js index 35bc914301..e4ceecc0ca 100644 --- a/src/components/directorybrowser/directorybrowser.js +++ b/src/components/directorybrowser/directorybrowser.js @@ -1,4 +1,4 @@ -define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'emby-button', 'paper-icon-button-light', 'css!./directorybrowser', 'formDialogStyle', 'emby-button'], function(loading, dialogHelper, dom) { +define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-icon-button-light', 'css!./directorybrowser', 'formDialogStyle', 'emby-button'], function(loading, dialogHelper, dom) { 'use strict'; function getSystemInfo() { diff --git a/src/components/filtermenu/filtermenu.js b/src/components/filtermenu/filtermenu.js index 02b35880b9..89457aa4e6 100644 --- a/src/components/filtermenu/filtermenu.js +++ b/src/components/filtermenu/filtermenu.js @@ -1,4 +1,4 @@ -define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', 'inputManager', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'userSettings', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'emby-button', 'flexStyles'], function (require, dom, focusManager, dialogHelper, loading, appHost, inputManager, layoutManager, connectionManager, appRouter, globalize, userSettings) { +define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', 'inputManager', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'userSettings', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (require, dom, focusManager, dialogHelper, loading, appHost, inputManager, layoutManager, connectionManager, appRouter, globalize, userSettings) { 'use strict'; function onSubmit(e) { diff --git a/src/components/homesections/homesections.js b/src/components/homesections/homesections.js index bf2a05ffba..0c30a015cc 100644 --- a/src/components/homesections/homesections.js +++ b/src/components/homesections/homesections.js @@ -1,4 +1,4 @@ -define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'layoutManager', 'imageLoader', 'globalize', 'itemShortcuts', 'itemHelper', 'appRouter', 'emby-button', 'paper-icon-button-light', 'emby-itemscontainer', 'emby-scroller', 'emby-button', 'css!./homesections'], function (connectionManager, cardBuilder, appSettings, dom, appHost, layoutManager, imageLoader, globalize, itemShortcuts, itemHelper, appRouter) { +define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'layoutManager', 'imageLoader', 'globalize', 'itemShortcuts', 'itemHelper', 'appRouter', 'paper-icon-button-light', 'emby-itemscontainer', 'emby-scroller', 'emby-button', 'css!./homesections'], function (connectionManager, cardBuilder, appSettings, dom, appHost, layoutManager, imageLoader, globalize, itemShortcuts, itemHelper, appRouter) { 'use strict'; function getDefaultSection(index) { diff --git a/src/components/imagedownloader/imagedownloader.js b/src/components/imagedownloader/imagedownloader.js index 9c6aab2725..729bce3382 100644 --- a/src/components/imagedownloader/imagedownloader.js +++ b/src/components/imagedownloader/imagedownloader.js @@ -1,4 +1,4 @@ -define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader', 'browser', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'emby-checkbox', 'emby-button', 'paper-icon-button-light', 'emby-button', 'formDialogStyle', 'cardStyle'], function (loading, appHost, dialogHelper, connectionManager, imageLoader, browser, layoutManager, scrollHelper, globalize, require) { +define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader', 'browser', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'emby-checkbox', 'paper-icon-button-light', 'emby-button', 'formDialogStyle', 'cardStyle'], function (loading, appHost, dialogHelper, connectionManager, imageLoader, browser, layoutManager, scrollHelper, globalize, require) { 'use strict'; var currentItemId; @@ -364,7 +364,7 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader' scrollHelper.centerFocus.on(dlg, false); } - // Has to be assigned a z-index after the call to .open() + // Has to be assigned a z-index after the call to .open() dlg.addEventListener('close', onDialogClosed); dialogHelper.open(dlg); diff --git a/src/components/maintabsmanager.js b/src/components/maintabsmanager.js index fa2922aafb..64e25b4870 100644 --- a/src/components/maintabsmanager.js +++ b/src/components/maintabsmanager.js @@ -1,4 +1,4 @@ -define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button', 'emby-button'], function (dom, browser, events) { +define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom, browser, events) { 'use strict'; var tabOwnerView; diff --git a/src/components/sortmenu/sortmenu.js b/src/components/sortmenu/sortmenu.js index 06e75c59cc..da2fcdaa7c 100644 --- a/src/components/sortmenu/sortmenu.js +++ b/src/components/sortmenu/sortmenu.js @@ -1,4 +1,4 @@ -define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'layoutManager', 'connectionManager', 'globalize', 'userSettings', 'emby-select', 'paper-icon-button-light', 'material-icons', 'css!./../formdialog', 'emby-button', 'emby-button', 'flexStyles'], function (require, dom, focusManager, dialogHelper, loading, layoutManager, connectionManager, globalize, userSettings) { +define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'layoutManager', 'connectionManager', 'globalize', 'userSettings', 'emby-select', 'paper-icon-button-light', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (require, dom, focusManager, dialogHelper, loading, layoutManager, connectionManager, globalize, userSettings) { 'use strict'; function onSubmit(e) { diff --git a/src/components/viewsettings/viewsettings.js b/src/components/viewsettings/viewsettings.js index bfeb7e66ff..617e021115 100644 --- a/src/components/viewsettings/viewsettings.js +++ b/src/components/viewsettings/viewsettings.js @@ -1,4 +1,4 @@ -define(['require', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'userSettings', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'emby-button', 'flexStyles'], function (require, dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize, userSettings) { +define(['require', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'userSettings', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (require, dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize, userSettings) { 'use strict'; function onSubmit(e) { From b3e6d6a83557eb5e2bf61bf35e76e536a175a161 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Mon, 25 Mar 2019 23:04:15 +0000 Subject: [PATCH 190/220] add missing emby-button dependency for addplugin --- src/addplugin.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addplugin.html b/src/addplugin.html index 38de32c207..5d5d5799d3 100644 --- a/src/addplugin.html +++ b/src/addplugin.html @@ -1,4 +1,4 @@ -
+
From 02c5fd688fa20af749653fc36ecbea1d1929327c Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Mon, 25 Mar 2019 23:08:04 +0000 Subject: [PATCH 191/220] removed old duplicate files for viewmanager --- src/components/viewmanager/package.json | 3 - src/components/viewmanager/viewContainer.css | 69 ------- src/components/viewmanager/viewManager.js | 183 ------------------- src/controllers/librarysettings.js | 2 +- 4 files changed, 1 insertion(+), 256 deletions(-) delete mode 100644 src/components/viewmanager/package.json delete mode 100644 src/components/viewmanager/viewContainer.css delete mode 100644 src/components/viewmanager/viewManager.js diff --git a/src/components/viewmanager/package.json b/src/components/viewmanager/package.json deleted file mode 100644 index 819371af71..0000000000 --- a/src/components/viewmanager/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "main": "viewManager.js" -} \ No newline at end of file diff --git a/src/components/viewmanager/viewContainer.css b/src/components/viewmanager/viewContainer.css deleted file mode 100644 index edfa101976..0000000000 --- a/src/components/viewmanager/viewContainer.css +++ /dev/null @@ -1,69 +0,0 @@ -.mainAnimatedPage { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - contain: layout style size; - /* Can't use will-change because it causes the alpha picker to move when the page scrolls*/ - /*will-change: transform;*/ -} - -@keyframes view-fadeout { - from { - opacity: 1; - } - - to { - opacity: 0; - } -} -@keyframes view-fadein { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} - -@keyframes view-slideleft { - from { - transform: translate3d(100%, 0, 0); - } - - to { - transform: none; - } -} - -@keyframes view-slideleft-r { - from { - transform: none; - } - - to { - transform: translate3d(-100%, 0, 0); - } -} - -@keyframes view-slideright { - from { - transform: translate3d(-100%, 0, 0); - } - - to { - transform: none; - } -} - -@keyframes view-slideright-r { - from { - transform: none; - } - - to { - transform: translate3d(100%, 0, 0); - } -} \ No newline at end of file diff --git a/src/components/viewmanager/viewManager.js b/src/components/viewmanager/viewManager.js deleted file mode 100644 index 606c7e98c1..0000000000 --- a/src/components/viewmanager/viewManager.js +++ /dev/null @@ -1,183 +0,0 @@ -define(['viewcontainer', 'focusManager', 'queryString', 'layoutManager'], function (viewcontainer, focusManager, queryString, layoutManager) { - 'use strict'; - - var currentView; - var dispatchPageEvents; - - viewcontainer.setOnBeforeChange(function (newView, isRestored, options) { - - var lastView = currentView; - if (lastView) { - - var beforeHideResult = dispatchViewEvent(lastView, null, 'viewbeforehide', true); - - if (!beforeHideResult) { - // todo: cancel - } - } - - var eventDetail = getViewEventDetail(newView, options, isRestored); - - if (!newView.initComplete) { - newView.initComplete = true; - - if (options.controllerFactory) { - - // Use controller method - var controller = new options.controllerFactory(newView, eventDetail.detail.params); - } - - if (!options.controllerFactory || dispatchPageEvents) { - dispatchViewEvent(newView, eventDetail, 'viewinit'); - } - } - - dispatchViewEvent(newView, eventDetail, 'viewbeforeshow'); - }); - - function onViewChange(view, options, isRestore) { - - var lastView = currentView; - if (lastView) { - dispatchViewEvent(lastView, null, 'viewhide'); - } - - currentView = view; - - var eventDetail = getViewEventDetail(view, options, isRestore); - - if (!isRestore) { - if (options.autoFocus !== false) { - focusManager.autoFocus(view); - } - } - else if (!layoutManager.mobile) { - if (view.activeElement && document.body.contains(view.activeElement) && focusManager.isCurrentlyFocusable(view.activeElement)) { - focusManager.focus(view.activeElement); - } else { - focusManager.autoFocus(view); - } - } - - view.dispatchEvent(new CustomEvent('viewshow', eventDetail)); - - if (dispatchPageEvents) { - view.dispatchEvent(new CustomEvent('pageshow', eventDetail)); - } - } - - function getProperties(view) { - var props = view.getAttribute('data-properties'); - - if (props) { - return props.split(','); - } - - return []; - } - - function dispatchViewEvent(view, eventInfo, eventName, isCancellable) { - - if (!eventInfo) { - eventInfo = { - detail: { - type: view.getAttribute('data-type'), - properties: getProperties(view) - }, - bubbles: true, - cancelable: isCancellable - }; - } - - eventInfo.cancelable = isCancellable || false; - - var eventResult = view.dispatchEvent(new CustomEvent(eventName, eventInfo)); - - if (dispatchPageEvents) { - eventInfo.cancelable = false; - view.dispatchEvent(new CustomEvent(eventName.replace('view', 'page'), eventInfo)); - } - - return eventResult; - } - - function getViewEventDetail(view, options, isRestore) { - - var url = options.url; - var index = url.indexOf('?'); - var params = index === -1 ? {} : queryString.parse(url.substring(index + 1)); - - return { - detail: { - type: view.getAttribute('data-type'), - properties: getProperties(view), - params: params, - isRestored: isRestore, - state: options.state, - - // The route options - options: options.options || {} - }, - bubbles: true, - cancelable: false - }; - } - - function resetCachedViews() { - // Reset all cached views whenever the skin changes - viewcontainer.reset(); - } - - document.addEventListener('skinunload', resetCachedViews); - - function ViewManager() { - } - - ViewManager.prototype.loadView = function (options) { - - var lastView = currentView; - - // Record the element that has focus - if (lastView) { - lastView.activeElement = document.activeElement; - } - - if (options.cancel) { - return; - } - - viewcontainer.loadView(options).then(function (view) { - - onViewChange(view, options); - }); - }; - - ViewManager.prototype.tryRestoreView = function (options, onViewChanging) { - - if (options.cancel) { - return Promise.reject({ cancelled: true }); - } - - // Record the element that has focus - if (currentView) { - currentView.activeElement = document.activeElement; - } - - return viewcontainer.tryRestoreView(options).then(function (view) { - - onViewChanging(); - onViewChange(view, options, true); - - }); - }; - - ViewManager.prototype.currentView = function () { - return currentView; - }; - - ViewManager.prototype.dispatchPageEvents = function (value) { - dispatchPageEvents = value; - }; - - return new ViewManager(); -}); diff --git a/src/controllers/librarysettings.js b/src/controllers/librarysettings.js index 997ccdfd4d..3fc9c40d98 100644 --- a/src/controllers/librarysettings.js +++ b/src/controllers/librarysettings.js @@ -88,4 +88,4 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked", "emby-checkbox", "emby- }); }); } -}); +}); \ No newline at end of file From 7a5d66c792060b288c91162175d18ef28d51e4c2 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Mon, 25 Mar 2019 23:43:03 +0000 Subject: [PATCH 192/220] refactor fullscreenManager suggested by JustAMan --- src/components/fullscreenManager.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/components/fullscreenManager.js b/src/components/fullscreenManager.js index 0a43a764a5..079267a6c4 100644 --- a/src/components/fullscreenManager.js +++ b/src/components/fullscreenManager.js @@ -81,16 +81,11 @@ define(['events', 'dom', 'apphost', 'browser'], function (events, dom, appHost, if (appHost.supports("fullscreenchange") && (browser.edgeUwp || -1 !== navigator.userAgent.toLowerCase().indexOf("electron"))) { function isTargetValid(target) { - - if (dom.parentWithTag(target, ['BUTTON', 'INPUT', 'TEXTAREA'])) { - return false; - } - - return true; + return !dom.parentWithTag(target, ['BUTTON', 'INPUT', 'TEXTAREA']); } - + dom.addEventListener(window, 'dblclick', function (e) { - + if (isTargetValid(e.target)) { if (manager.isFullScreen()) { manager.exitFullscreen(); @@ -98,7 +93,7 @@ define(['events', 'dom', 'apphost', 'browser'], function (events, dom, appHost, manager.requestFullscreen(); } } - + }, { passive: true }); From ac13bcb43ec9f383a7a54c5ba92e57d13e71a128 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Tue, 26 Mar 2019 01:44:33 +0000 Subject: [PATCH 193/220] force emby-button load before routes --- src/scripts/site.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 42bb9f1587..f984f20ebb 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -581,7 +581,7 @@ var AppInfo = {}; window.Emby.Page = appRouter; - require(['scripts/themeloader', 'libraryMenu', 'scripts/routes'], function () { + require(['emby-button', 'scripts/themeloader', 'libraryMenu', 'scripts/routes'], function () { Emby.Page.start({ click: false, hashbang: true From 67f04532bed2eac19abc0216f951dd872997bb29 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Tue, 26 Mar 2019 01:45:36 +0000 Subject: [PATCH 194/220] fix minor bug for listItemImage background sizing --- src/components/listview/listview.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/listview/listview.css b/src/components/listview/listview.css index 4b4e88f842..312bf14a16 100644 --- a/src/components/listview/listview.css +++ b/src/components/listview/listview.css @@ -100,7 +100,7 @@ min-width: 2.78em; min-height: 2.78em; background-repeat: no-repeat; - background-size: contain; + background-size: cover; flex-shrink: 0; background-position: center center; position: relative; From 5ff34f5eb4d44522e2aa9aa0bc86bca539c2607f Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Thu, 28 Mar 2019 22:17:46 +0000 Subject: [PATCH 195/220] removed unecessary file page.js from components --- src/components/page.js | 1077 ---------------------------------------- 1 file changed, 1077 deletions(-) delete mode 100644 src/components/page.js diff --git a/src/components/page.js b/src/components/page.js deleted file mode 100644 index ce96fd185e..0000000000 --- a/src/components/page.js +++ /dev/null @@ -1,1077 +0,0 @@ -define([], function () { - - 'use strict'; - - /** - * Detect click event - */ - var clickEvent = ('undefined' !== typeof document) && document.ontouchstart ? 'touchstart' : 'click'; - - /** - * To work properly with the URL - * history.location generated polyfill in https://github.com/devote/HTML5-History-API - */ - - var location = ('undefined' !== typeof window) && (window.history.location || window.location); - - /** - * Perform initial dispatch. - */ - - var dispatch = true; - - - /** - * Decode URL components (query string, pathname, hash). - * Accommodates both regular percent encoding and x-www-form-urlencoded format. - */ - var decodeURLComponents = true; - - /** - * Base path. - */ - - var base = ''; - - /** - * Running flag. - */ - - var running; - - /** - * HashBang option - */ - - var hashbang = false; - - var enableHistory = false; - - /** - * Previous context, for capturing - * page exit events. - */ - - var prevContext; - - var prevPageContext; - - /** - * Register `path` with callback `fn()`, - * or route `path`, or redirection, - * or `page.start()`. - * - * page(fn); - * page('*', fn); - * page('/user/:id', load, user); - * page('/user/' + user.id, { some: 'thing' }); - * page('/user/' + user.id); - * page('/from', '/to') - * page(); - * - * @param {String|Function} path - * @param {Function} fn... - * @api public - */ - - function page(path, fn) { - // - if ('function' === typeof path) { - return page('*', path); - } - - // route to - if ('function' === typeof fn) { - var route = new Route(path); - for (var i = 1; i < arguments.length; ++i) { - page.callbacks.push(route.middleware(arguments[i])); - } - // show with [state] - } else if ('string' === typeof path) { - page['string' === typeof fn ? 'redirect' : 'show'](path, fn); - // start [options] - } else { - page.start(path); - } - } - - /** - * Callback functions. - */ - - page.callbacks = []; - page.exits = []; - - /** - * Current path being processed - * @type {String} - */ - page.current = ''; - - /** - * Number of pages navigated to. - * @type {number} - * - * page.len == 0; - * page('/login'); - * page.len == 1; - */ - - page.len = 0; - - /** - * Get or set basepath to `path`. - * - * @param {String} path - * @api public - */ - - page.base = function (path) { - if (0 === arguments.length) { - return base; - } - base = path; - }; - - /** - * Bind with the given `options`. - * - * Options: - * - * - `click` bind to click events [true] - * - `popstate` bind to popstate [true] - * - `dispatch` perform initial dispatch [true] - * - * @param {Object} options - * @api public - */ - - page.start = function (options) { - options = options || {}; - if (running) { - return; - } - running = true; - if (false === options.dispatch) { - dispatch = false; - } - if (false === options.decodeURLComponents) { - decodeURLComponents = false; - } - if (false !== options.popstate) { - window.addEventListener('popstate', onpopstate, false); - } - if (false !== options.click) { - document.addEventListener(clickEvent, onclick, false); - } - if (options.enableHistory != null) { - enableHistory = options.enableHistory; - } - if (true === options.hashbang) { - hashbang = true; - } - if (!dispatch) { - return; - } - - var url; - - if (hashbang && ~location.hash.indexOf('#!')) { - - url = location.hash.substr(2); - - var href = location.href.toString(); - if (href.indexOf('?') >= href.indexOf('#!')) { - url += location.search; - } - } - else { - url = location.pathname + location.search + location.hash; - } - - page.replace(url, null, true, dispatch); - }; - - /** - * Unbind click and popstate event handlers. - * - * @api public - */ - - page.stop = function () { - if (!running) { - return; - } - page.current = ''; - page.len = 0; - running = false; - document.removeEventListener(clickEvent, onclick, false); - window.removeEventListener('popstate', onpopstate, false); - }; - - /** - * Show `path` with optional `state` object. - * - * @param {String} path - * @param {Object} state - * @param {Boolean} dispatch - * @return {Context} - * @api public - */ - - page.show = function (path, state, dispatch, push, isBack) { - var ctx = new Context(path, state); - ctx.isBack = isBack; - page.current = ctx.path; - if (false !== dispatch) { - page.dispatch(ctx); - } - if (false !== ctx.handled && false !== push) { - ctx.pushState(); - } - return ctx; - }; - - page.restorePreviousState = function () { - - prevContext = prevPageContext; - page.show(prevContext.pathname, prevContext.state, false, true, false); - }; - - /** - * Goes back in the history - * Back should always let the current route push state and then go back. - * - * @param {String} path - fallback path to go back if no more history exists, if undefined defaults to page.base - * @param {Object} [state] - * @api public - */ - - page.back = function (path, state) { - - if (enableHistory) { - // Keep it simple and mimic browser back - history.back(); - return; - } - - if (page.len > 0) { - // this may need more testing to see if all browsers - // wait for the next tick to go back in history - if (enableHistory) { - history.back(); - } else { - - if (backStack.length > 2) { - backStack.length--; - var previousState = backStack[backStack.length - 1]; - page.show(previousState.path, previousState.state, true, false, true); - } - } - page.len--; - } else if (path) { - setTimeout(function () { - page.show(path, state); - }); - } else { - setTimeout(function () { - page.show(base, state); - }); - } - }; - - page.enableNativeHistory = function () { - return enableHistory; - }; - - page.canGoBack = function () { - if (enableHistory) { - return history.length > 1; - } - return (page.len || 0) > 0; - }; - - /** - * Register route to redirect from one path to other - * or just redirect to another route - * - * @param {String} from - if param 'to' is undefined redirects to 'from' - * @param {String} [to] - * @api public - */ - page.redirect = function (from, to) { - // Define route from a path to another - if ('string' === typeof from && 'string' === typeof to) { - page(from, function (e) { - setTimeout(function () { - page.replace(to); - }, 0); - }); - } - - // Wait for the push state and replace it with another - if ('string' === typeof from && 'undefined' === typeof to) { - setTimeout(function () { - page.replace(from); - }, 0); - } - }; - - /** - * Replace `path` with optional `state` object. - * - * @param {String} path - * @param {Object} state - * @return {Context} - * @api public - */ - - - page.replace = function (path, state, init, dispatch, isBack) { - var ctx = new Context(path, state); - ctx.isBack = isBack; - page.current = ctx.path; - ctx.init = init; - ctx.save(); // save before dispatching, which may redirect - if (false !== dispatch) { - page.dispatch(ctx); - } - return ctx; - }; - - /** - * Dispatch the given `ctx`. - * - * @param {Object} ctx - * @api private - */ - - page.dispatch = function (ctx) { - var prev = prevContext, - i = 0, - j = 0; - - prevPageContext = prevContext; - prevContext = ctx; - - function nextExit() { - var fn = page.exits[j++]; - if (!fn) { - return nextEnter(); - } - fn(prev, nextExit); - } - - function nextEnter() { - var fn = page.callbacks[i++]; - - if (ctx.path !== page.current) { - ctx.handled = false; - return; - } - if (!fn) { - return unhandled(ctx); - } - fn(ctx, nextEnter); - } - - if (prev) { - nextExit(); - } else { - nextEnter(); - } - }; - - /** - * Unhandled `ctx`. When it's not the initial - * popstate then redirect. If you wish to handle - * 404s on your own use `page('*', callback)`. - * - * @param {Context} ctx - * @api private - */ - - function unhandled(ctx) { - if (ctx.handled) { - return; - } - var current; - - if (hashbang) { - current = base + location.hash.replace('#!', ''); - } else { - current = location.pathname + location.search; - } - - if (current === ctx.canonicalPath) { - return; - } - page.stop(); - ctx.handled = false; - location.href = ctx.canonicalPath; - } - - /** - * Register an exit route on `path` with - * callback `fn()`, which will be called - * on the previous context when a new - * page is visited. - */ - page.exit = function (path, fn) { - if (typeof path === 'function') { - return page.exit('*', path); - } - - var route = new Route(path); - for (var i = 1; i < arguments.length; ++i) { - page.exits.push(route.middleware(arguments[i])); - } - }; - - /** - * Remove URL encoding from the given `str`. - * Accommodates whitespace in both x-www-form-urlencoded - * and regular percent-encoded form. - * - * @param {str} URL component to decode - */ - function decodeURLEncodedURIComponent(val) { - if (typeof val !== 'string') { return val; } - return decodeURLComponents ? decodeURIComponent(val.replace(/\+/g, ' ')) : val; - } - - /** - * Initialize a new "request" `Context` - * with the given `path` and optional initial `state`. - * - * @param {String} path - * @param {Object} state - * @api public - */ - - function Context(path, state) { - if ('/' === path[0] && 0 !== path.indexOf(base)) { - path = base + (hashbang ? '#!' : '') + path; - } - var i = path.indexOf('?'); - - this.canonicalPath = path; - this.path = path.replace(base, '') || '/'; - if (hashbang) { - this.path = this.path.replace('#!', '') || '/'; - } - - this.title = document.title; - this.state = state || {}; - this.state.path = path; - this.querystring = ~i ? decodeURLEncodedURIComponent(path.slice(i + 1)) : ''; - this.pathname = decodeURLEncodedURIComponent(~i ? path.slice(0, i) : path); - this.params = {}; - - // fragment - this.hash = ''; - if (!hashbang) { - if (!~this.path.indexOf('#')) { - return; - } - var parts = this.path.split('#'); - this.path = parts[0]; - this.hash = decodeURLEncodedURIComponent(parts[1]) || ''; - this.querystring = this.querystring.split('#')[0]; - } - } - - /** - * Expose `Context`. - */ - - page.Context = Context; - var backStack = []; - - /** - * Push state. - * - * @api private - */ - - Context.prototype.pushState = function () { - page.len++; - - if (enableHistory) { - history.pushState(this.state, this.title, hashbang && this.path !== '/' ? '#!' + this.path : this.canonicalPath); - } else { - backStack.push({ - state: this.state, - title: this.title, - url: (hashbang && this.path !== '/' ? '#!' + this.path : this.canonicalPath), - path: this.path - }); - } - }; - - /** - * Save the context state. - * - * @api public - */ - - Context.prototype.save = function () { - - if (enableHistory) { - history.replaceState(this.state, this.title, hashbang && this.path !== '/' ? '#!' + this.path : this.canonicalPath); - } else { - backStack[page.len || 0] = { - state: this.state, - title: this.title, - url: (hashbang && this.path !== '/' ? '#!' + this.path : this.canonicalPath), - path: this.path - }; - } - }; - - /** - * Initialize `Route` with the given HTTP `path`, - * and an array of `callbacks` and `options`. - * - * Options: - * - * - `sensitive` enable case-sensitive routes - * - `strict` enable strict matching for trailing slashes - * - * @param {String} path - * @param {Object} options. - * @api private - */ - - function Route(path, options) { - options = options || {}; - this.path = (path === '*') ? '(.*)' : path; - this.method = 'GET'; - this.regexp = pathToRegexp(this.path, - this.keys = [], - options.sensitive, - options.strict); - } - - /** - * Expose `Route`. - */ - - page.Route = Route; - - /** - * Return route middleware with - * the given callback `fn()`. - * - * @param {Function} fn - * @return {Function} - * @api public - */ - - Route.prototype.middleware = function (fn) { - var self = this; - return function (ctx, next) { - if (self.match(ctx.path, ctx.params)) { - return fn(ctx, next); - } - next(); - }; - }; - - /** - * Check if this route matches `path`, if so - * populate `params`. - * - * @param {String} path - * @param {Object} params - * @return {Boolean} - * @api private - */ - - Route.prototype.match = function (path, params) { - var keys = this.keys, - qsIndex = path.indexOf('?'), - pathname = ~qsIndex ? path.slice(0, qsIndex) : path, - m = this.regexp.exec(decodeURIComponent(pathname)); - - if (!m) { - return false; - } - - for (var i = 1, len = m.length; i < len; ++i) { - var key = keys[i - 1]; - var val = decodeURLEncodedURIComponent(m[i]); - if (val !== undefined || !(hasOwnProperty.call(params, key.name))) { - params[key.name] = val; - } - } - - return true; - }; - - - var previousPopState = {}; - - function ignorePopState(event) { - - var state = event.state || {}; - - if (previousPopState.navigate === false) { - // Ignore - previousPopState = state; - return true; - } - - previousPopState = state; - return false; - } - - page.pushState = function (state, title, url) { - - if (hashbang) { - url = '#!' + url; - } - - history.pushState(state, title, url); - previousPopState = state; - }; - - /** - * Handle "populate" events. - */ - - var onpopstate = (function () { - var loaded = false; - if ('undefined' === typeof window) { - return; - } - if (document.readyState === 'complete') { - loaded = true; - } else { - window.addEventListener('load', function () { - setTimeout(function () { - loaded = true; - }, 0); - }); - } - return function onpopstate(e) { - if (!loaded) { - return; - } - if (ignorePopState(e)) { - return; - } - if (e.state) { - var path = e.state.path; - page.replace(path, e.state, null, null, true); - } else { - page.show(location.pathname + location.hash, undefined, undefined, false, true); - } - }; - })(); - /** - * Handle "click" events. - */ - - function onclick(e, checkWhich) { - - if (1 !== which(e) && checkWhich !== false) { - return; - } - - if (e.metaKey || e.ctrlKey || e.shiftKey) { - return; - } - if (e.defaultPrevented) { - return; - } - - - // ensure link - var el = e.target; - - while (el && 'A' !== el.nodeName) { - el = el.parentNode; - } - if (!el || 'A' !== el.nodeName) { - return; - } - - - // Ignore if tag has - // 1. "download" attribute - // 2. rel="external" attribute - if (el.hasAttribute('download') || el.getAttribute('rel') === 'external') { - return; - } - - // ensure non-hash for the same path - var link = el.getAttribute('href'); - if (link === '#') { - e.preventDefault(); - return; - } - - if (!hashbang && el.pathname === location.pathname && (el.hash || '#' === link)) { - return; - } - - // check target - if (el.target) { - return; - } - - // x-origin - if (!sameOrigin(el.href)) { - return; - } - - // rebuild path - var path = el.pathname + el.search + (el.hash || ''); - - // same page - var orig = path; - - if (path.indexOf(base) === 0) { - path = path.substr(base.length); - } - - if (hashbang) { - path = path.replace('#!', ''); - } - - if (base && orig === path) { - // This is causing navigation to be canceled in edge uwp - // If needed this can be changed to only be skipped when called via handleAnchorClick - //return; - } - - e.preventDefault(); - page.show(orig); - } - - page.handleAnchorClick = onclick; - - /** - * Event button. - */ - - function which(e) { - e = e || window.event; - return null === e.which ? e.button : e.which; - } - - /** - * Check if `href` is the same origin. - */ - - function sameOrigin(href) { - var origin = location.protocol + '//' + location.hostname; - if (location.port) { - origin += ':' + location.port; - } - return (href && (0 === href.indexOf(origin))); - } - - page.sameOrigin = sameOrigin; - - /** - * The main path matching regexp utility. - * - * @type {RegExp} - */ - var PATH_REGEXP = new RegExp([ - // Match escaped characters that would otherwise appear in future matches. - // This allows the user to escape special characters that won't transform. - '(\\\\.)', - // Match Express-style parameters and un-named parameters with a prefix - // and optional suffixes. Matches appear as: - // - // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined] - // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined] - // "/*" => ["/", undefined, undefined, undefined, undefined, "*"] - '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^()])+)\\))?|\\(((?:\\\\.|[^()])+)\\))([+*?])?|(\\*))' - ].join('|'), 'g'); - - /** - * Parse a string for the raw tokens. - * - * @param {String} str - * @return {Array} - */ - function parse(str) { - var tokens = []; - var key = 0; - var index = 0; - var path = ''; - var res; - - while ((res = PATH_REGEXP.exec(str)) != null) { - var m = res[0]; - var escaped = res[1]; - var offset = res.index; - path += str.slice(index, offset); - index = offset + m.length; - - // Ignore already escaped sequences. - if (escaped) { - path += escaped[1]; - continue; - } - - // Push the current path onto the tokens. - if (path) { - tokens.push(path); - path = ''; - } - - var prefix = res[2]; - var name = res[3]; - var capture = res[4]; - var group = res[5]; - var suffix = res[6]; - var asterisk = res[7]; - - var repeat = suffix === '+' || suffix === '*'; - var optional = suffix === '?' || suffix === '*'; - var delimiter = prefix || '/'; - var pattern = capture || group || (asterisk ? '.*' : '[^' + delimiter + ']+?'); - - tokens.push({ - name: name || key++, - prefix: prefix || '', - delimiter: delimiter, - optional: optional, - repeat: repeat, - pattern: escapeGroup(pattern) - }); - } - - // Match any characters still remaining. - if (index < str.length) { - path += str.substr(index); - } - - // If the path exists, push it onto the end. - if (path) { - tokens.push(path); - } - - return tokens; - } - - var isarray = Array.isArray || function (arr) { - return Object.prototype.toString.call(arr) === '[object Array]'; - }; - - /** - * Escape a regular expression string. - * - * @param {String} str - * @return {String} - */ - function escapeString(str) { - return str.replace(/([.+*?=^!:${}()[\]|\/])/g, '\\$1'); - } - - /** - * Escape the capturing group by escaping special characters and meaning. - * - * @param {String} group - * @return {String} - */ - function escapeGroup(group) { - return group.replace(/([=!:$\/()])/g, '\\$1'); - } - - /** - * Attach the keys as a property of the regexp. - * - * @param {RegExp} re - * @param {Array} keys - * @return {RegExp} - */ - function attachKeys(re, keys) { - re.keys = keys; - return re; - } - - /** - * Get the flags for a regexp from the options. - * - * @param {Object} options - * @return {String} - */ - function flags(options) { - return options.sensitive ? '' : 'i'; - } - - /** - * Pull out keys from a regexp. - * - * @param {RegExp} path - * @param {Array} keys - * @return {RegExp} - */ - function regexpToRegexp(path, keys) { - // Use a negative lookahead to match only capturing groups. - var groups = path.source.match(/\((?!\?)/g); - - if (groups) { - for (var i = 0; i < groups.length; i++) { - keys.push({ - name: i, - prefix: null, - delimiter: null, - optional: false, - repeat: false, - pattern: null - }); - } - } - - return attachKeys(path, keys); - } - - /** - * Transform an array into a regexp. - * - * @param {Array} path - * @param {Array} keys - * @param {Object} options - * @return {RegExp} - */ - function arrayToRegexp(path, keys, options) { - var parts = []; - - for (var i = 0; i < path.length; i++) { - parts.push(pathToRegexp(path[i], keys, options).source); - } - - var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options)); - - return attachKeys(regexp, keys); - } - - /** - * Create a path regexp from string input. - * - * @param {String} path - * @param {Array} keys - * @param {Object} options - * @return {RegExp} - */ - function stringToRegexp(path, keys, options) { - var tokens = parse(path); - var re = tokensToRegExp(tokens, options); - - // Attach keys back to the regexp. - for (var i = 0; i < tokens.length; i++) { - if (typeof tokens[i] !== 'string') { - keys.push(tokens[i]); - } - } - - return attachKeys(re, keys); - } - - /** - * Expose a function for taking tokens and returning a RegExp. - * - * @param {Array} tokens - * @param {Array} keys - * @param {Object} options - * @return {RegExp} - */ - function tokensToRegExp(tokens, options) { - options = options || {}; - - var strict = options.strict; - var end = options.end !== false; - var route = ''; - var lastToken = tokens[tokens.length - 1]; - var endsWithSlash = typeof lastToken === 'string' && /\/$/.test(lastToken); - - // Iterate over the tokens and create our regexp string. - for (var i = 0; i < tokens.length; i++) { - var token = tokens[i]; - - if (typeof token === 'string') { - route += escapeString(token); - } else { - var prefix = escapeString(token.prefix); - var capture = token.pattern; - - if (token.repeat) { - capture += '(?:' + prefix + capture + ')*'; - } - - if (token.optional) { - if (prefix) { - capture = '(?:' + prefix + '(' + capture + '))?'; - } else { - capture = '(' + capture + ')?'; - } - } else { - capture = prefix + '(' + capture + ')'; - } - - route += capture; - } - } - - // In non-strict mode we allow a slash at the end of match. If the path to - // match already ends with a slash, we remove it for consistency. The slash - // is valid at the end of a path match, not in the middle. This is important - // in non-ending mode, where "/test/" shouldn't match "/test//route". - if (!strict) { - route = (endsWithSlash ? route.slice(0, -2) : route) + '(?:\\/(?=$))?'; - } - - if (end) { - route += '$'; - } else { - // In non-ending mode, we need the capturing groups to match as much as - // possible by using a positive lookahead to the end or next path segment. - route += strict && endsWithSlash ? '' : '(?=\\/|$)'; - } - - return new RegExp('^' + route, flags(options)); - } - - /** - * Normalize the given path string, returning a regular expression. - * - * An empty array can be passed in for the keys, which will hold the - * placeholder key descriptions. For example, using `/user/:id`, `keys` will - * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`. - * - * @param {(String|RegExp|Array)} path - * @param {Array} [keys] - * @param {Object} [options] - * @return {RegExp} - */ - function pathToRegexp(path, keys, options) { - keys = keys || []; - - if (!isarray(keys)) { - options = keys; - keys = []; - } else if (!options) { - options = {}; - } - - if (path instanceof RegExp) { - return regexpToRegexp(path, keys, options); - } - - if (isarray(path)) { - return arrayToRegexp(path, keys, options); - } - - return stringToRegexp(path, keys, options); - } - - return page; - -}); \ No newline at end of file From 37cc900a8e50de1f0285d2484e3ca0c0e9eac464 Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Fri, 29 Mar 2019 07:12:15 -0700 Subject: [PATCH 196/220] Update src/strings/en-us.json Co-Authored-By: LogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com> --- src/strings/en-us.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index c65eab375c..a6c3955885 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -40,7 +40,7 @@ "AspectRatio": "Aspect ratio", "AttributeNew": "New", "Audio": "Audio", - "AuthProviderHelp": "Select an Authentication Provider to be used to Authenticate this user's password", + "AuthProviderHelp": "Select an Authentication Provider to be used to authenticate this user's password", "Auto": "Auto", "AutoBasedOnLanguageSetting": "Auto (based on language setting)", "Backdrop": "Backdrop", From e071c2fdcd14ae42ca52a28baf2fe6829448c61e Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Sat, 30 Mar 2019 22:10:45 +0300 Subject: [PATCH 197/220] readd missing strings --- src/strings/en-us.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index d39c7f9eae..cdc70bddda 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -928,6 +928,12 @@ "MediaInfoSampleRate": "Sample rate", "MediaInfoSize": "Size", "MediaInfoTimestamp": "Timestamp", + "MediaInfoSoftware": "Software", + "MediaInfoStreamTypeAudio": "Audio", + "MediaInfoStreamTypeData": "Data", + "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", + "MediaInfoStreamTypeSubtitle": "Subtitle", + "MediaInfoStreamTypeVideo": "Video", "MediaIsBeingConverted": "The media is being converted into a format that is compatible with the device that is playing the media.", "Menu": "Menu", "MessageAlreadyInstalled": "This version is already installed.", From e705fb7598ba49cb6041c0ebc9f27b87e7aaaa92 Mon Sep 17 00:00:00 2001 From: vitorsemeano Date: Sat, 30 Mar 2019 23:28:42 +0000 Subject: [PATCH 198/220] solve dark pane overlay when playing next track --- src/components/playback/playbackmanager.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 33b0b2b793..fedf7924ba 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -1731,7 +1731,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla var maxBitrate = params.MaxStreamingBitrate || self.getMaxStreamingBitrate(player); - var currentPlayOptions = currentItem.playOptions || {}; + var currentPlayOptions = currentItem.playOptions || getDefaultPlayOptions(); getPlaybackInfo(player, apiClient, currentItem, deviceProfile, maxBitrate, ticks, true, currentMediaSource.Id, audioStreamIndex, subtitleStreamIndex, liveStreamId, params.EnableDirectPlay, params.EnableDirectStream, params.AllowVideoStreamCopy, params.AllowAudioStreamCopy).then(function (result) { @@ -2698,7 +2698,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla if (newItem) { - var newItemPlayOptions = newItem.playOptions || {}; + var newItemPlayOptions = newItem.playOptions || getDefaultPlayOptions(); playInternal(newItem, newItemPlayOptions, function () { setPlaylistState(newItem.PlaylistItemId, newItemIndex); @@ -2803,7 +2803,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla console.log('playing next track'); - var newItemPlayOptions = newItemInfo.item.playOptions || {}; + var newItemPlayOptions = newItemInfo.item.playOptions || getDefaultPlayOptions(); playInternal(newItemInfo.item, newItemPlayOptions, function () { setPlaylistState(newItemInfo.item.PlaylistItemId, newItemInfo.index); @@ -2826,7 +2826,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla if (newItem) { - var newItemPlayOptions = newItem.playOptions || {}; + var newItemPlayOptions = newItem.playOptions || getDefaultPlayOptions(); newItemPlayOptions.startPositionTicks = 0; playInternal(newItem, newItemPlayOptions, function () { @@ -2997,7 +2997,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla var player = this; setCurrentPlayerInternal(player); - var playOptions = item.playOptions || {}; + var playOptions = item.playOptions || getDefaultPlayOptions(); var isFirstItem = playOptions.isFirstItem; var fullscreen = playOptions.fullscreen; From 732d8b5e26f0109643e424d38978622810a723c0 Mon Sep 17 00:00:00 2001 From: Froghut Date: Sun, 31 Mar 2019 12:05:54 +0200 Subject: [PATCH 199/220] When changing volume connected to chromecast change the device volume instead of the jellyfin-player volume --- src/components/chromecast/chromecastplayer.js | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/components/chromecast/chromecastplayer.js b/src/components/chromecast/chromecastplayer.js index d276bb4de2..cb63e9c4a8 100644 --- a/src/components/chromecast/chromecastplayer.js +++ b/src/components/chromecast/chromecastplayer.js @@ -779,12 +779,15 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', ' }); }; - ChromecastPlayer.prototype.volumeDown = function () { + ChromecastPlayer.prototype.volumeDown = function () { + vol = this._castPlayer.session.receiver.volume.level; + if (vol == null) + vol = 0.5; + vol -= 0.02; + vol = Math.max(vol, 0); + + this._castPlayer.session.setReceiverVolumeLevel(vol); - this._castPlayer.sendMessage({ - options: {}, - command: 'VolumeDown' - }); }; ChromecastPlayer.prototype.endSession = function () { @@ -799,24 +802,22 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', ' }; ChromecastPlayer.prototype.volumeUp = function () { + vol = this._castPlayer.session.receiver.volume.level; + if (vol == null) + vol = 0.5; + vol += 0.02; + vol = Math.min(vol, 1); - this._castPlayer.sendMessage({ - options: {}, - command: 'VolumeUp' - }); + this._castPlayer.session.setReceiverVolumeLevel(vol); }; ChromecastPlayer.prototype.setVolume = function (vol) { vol = Math.min(vol, 100); vol = Math.max(vol, 0); - - this._castPlayer.sendMessage({ - options: { - volume: vol - }, - command: 'SetVolume' - }); + vol = vol / 100; + + this._castPlayer.session.setReceiverVolumeLevel(vol); }; ChromecastPlayer.prototype.unpause = function () { From 35e63bd9e7b236dbec60ae81d7a05cf25f878cbb Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Sun, 31 Mar 2019 19:33:53 +0300 Subject: [PATCH 200/220] fix Indentation --- src/strings/en-us.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index cdc70bddda..fd82736769 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -928,12 +928,12 @@ "MediaInfoSampleRate": "Sample rate", "MediaInfoSize": "Size", "MediaInfoTimestamp": "Timestamp", - "MediaInfoSoftware": "Software", - "MediaInfoStreamTypeAudio": "Audio", - "MediaInfoStreamTypeData": "Data", - "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", - "MediaInfoStreamTypeSubtitle": "Subtitle", - "MediaInfoStreamTypeVideo": "Video", + "MediaInfoSoftware": "Software", + "MediaInfoStreamTypeAudio": "Audio", + "MediaInfoStreamTypeData": "Data", + "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", + "MediaInfoStreamTypeSubtitle": "Subtitle", + "MediaInfoStreamTypeVideo": "Video", "MediaIsBeingConverted": "The media is being converted into a format that is compatible with the device that is playing the media.", "Menu": "Menu", "MessageAlreadyInstalled": "This version is already installed.", From 49fd86d707781aa9fded2f02aaca02b4a75a19da Mon Sep 17 00:00:00 2001 From: Froghut Date: Mon, 1 Apr 2019 14:34:50 +0200 Subject: [PATCH 201/220] on chromecast playback stop still remember device volume/mute --- src/components/chromecast/chromecastplayer.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/chromecast/chromecastplayer.js b/src/components/chromecast/chromecastplayer.js index d276bb4de2..efa2bc70c6 100644 --- a/src/components/chromecast/chromecastplayer.js +++ b/src/components/chromecast/chromecastplayer.js @@ -574,8 +574,15 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', ' events.trigger(instance, "playbackstop", [state]); + var state = instance.lastPlayerData.PlayState || {}; + var volume = state.VolumeLevel; + var mute = state.IsMuted; + // Reset this so the next query doesn't make it appear like content is playing. instance.lastPlayerData = {}; + instance.lastPlayerData.PlayState = {}; + instance.lastPlayerData.PlayState.VolumeLevel = volume; + instance.lastPlayerData.PlayState.IsMuted = mute; }); events.on(instance._castPlayer, "playbackprogress", function (e, data) { From 37f63f696337330919087bb4e20d23368f985ea8 Mon Sep 17 00:00:00 2001 From: Froghut Date: Mon, 1 Apr 2019 15:34:01 +0200 Subject: [PATCH 202/220] add braces for clarification --- src/components/chromecast/chromecastplayer.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/chromecast/chromecastplayer.js b/src/components/chromecast/chromecastplayer.js index cb63e9c4a8..5a174bc019 100644 --- a/src/components/chromecast/chromecastplayer.js +++ b/src/components/chromecast/chromecastplayer.js @@ -782,7 +782,9 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', ' ChromecastPlayer.prototype.volumeDown = function () { vol = this._castPlayer.session.receiver.volume.level; if (vol == null) + { vol = 0.5; + } vol -= 0.02; vol = Math.max(vol, 0); @@ -804,7 +806,9 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', ' ChromecastPlayer.prototype.volumeUp = function () { vol = this._castPlayer.session.receiver.volume.level; if (vol == null) + { vol = 0.5; + } vol += 0.02; vol = Math.min(vol, 1); From 82d7b0eefb85793d5972018ab6e9e435bce3e4fa Mon Sep 17 00:00:00 2001 From: Froghut Date: Mon, 1 Apr 2019 15:40:10 +0200 Subject: [PATCH 203/220] add fallback defaults to volume/mute if null on playbackstop --- src/components/chromecast/chromecastplayer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/chromecast/chromecastplayer.js b/src/components/chromecast/chromecastplayer.js index efa2bc70c6..c20a9b57ab 100644 --- a/src/components/chromecast/chromecastplayer.js +++ b/src/components/chromecast/chromecastplayer.js @@ -575,8 +575,8 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', ' events.trigger(instance, "playbackstop", [state]); var state = instance.lastPlayerData.PlayState || {}; - var volume = state.VolumeLevel; - var mute = state.IsMuted; + var volume = state.VolumeLevel || 0.5; + var mute = state.IsMuted || false; // Reset this so the next query doesn't make it appear like content is playing. instance.lastPlayerData = {}; From 274ef0e532301f1af67e20176b41490b161d0424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Grenotton?= Date: Mon, 1 Apr 2019 16:07:56 +0200 Subject: [PATCH 204/220] Fix local chromecast play behind reverse proxy When using a HTTPS reverse proxy (for eg. traefik in fron of docker jellyfin), there's no valid advertised local address. Let's default to external one in such case, relying on the home router to properly route it internally. --- src/components/chromecast/chromecasthelpers.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/chromecast/chromecasthelpers.js b/src/components/chromecast/chromecasthelpers.js index c86233207d..0beba824c0 100644 --- a/src/components/chromecast/chromecasthelpers.js +++ b/src/components/chromecast/chromecasthelpers.js @@ -187,8 +187,13 @@ define(['events'], function (events) { return apiClient.getEndpointInfo().then(function (endpoint) { if (endpoint.IsInNetwork) { return apiClient.getPublicSystemInfo().then(function (info) { - addToCache(serverAddress, info.LocalAddress); - return info.LocalAddress; + var localAddress = info.LocalAddress + if (!localAddress) { + console.log("No valid local address returned, defaulting to external one") + localAddress = serverAddress; + } + addToCache(serverAddress, localAddress); + return localAddress; }); } else { addToCache(serverAddress, serverAddress); From 4baad878ac8ecab066695ec4a92ef2777f5bfa37 Mon Sep 17 00:00:00 2001 From: Froghut Date: Tue, 2 Apr 2019 09:43:49 +0200 Subject: [PATCH 205/220] when connected to chromecast make thehardware volume buttons change the chromecast device volume + fix volumeUp and columeDown missing var's --- src/components/chromecast/chromecastplayer.js | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/components/chromecast/chromecastplayer.js b/src/components/chromecast/chromecastplayer.js index 06c0279007..9b382aeecf 100644 --- a/src/components/chromecast/chromecastplayer.js +++ b/src/components/chromecast/chromecastplayer.js @@ -220,7 +220,9 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', ' this.session = null; this.deviceState = DEVICE_STATE.IDLE; this.castPlayerState = PLAYER_STATE.IDLE; - + document.removeEventListener("volumeupbutton", onVolumeUpKeyDown, false); + document.removeEventListener("volumedownbutton", onVolumeDownKeyDown, false); + //console.log('sessionUpdateListener: setting currentMediaSession to null'); this.currentMediaSession = null; @@ -258,6 +260,9 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', ' this.session.addMediaListener(this.sessionMediaListener.bind(this)); this.session.addUpdateListener(this.sessionUpdateListener.bind(this)); + document.addEventListener("volumeupbutton", onVolumeUpKeyDown, false); + document.addEventListener("volumedownbutton", onVolumeDownKeyDown, false); + events.trigger(this, 'connect'); this.sendMessage({ @@ -266,6 +271,14 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', ' }); }; + function onVolumeUpKeyDown() { + playbackManager.volumeUp(); + } + + function onVolumeDownKeyDown() { + playbackManager.volumeDown(); + } + /** * session update listener */ @@ -305,6 +318,8 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', ' //console.log(message); this.deviceState = DEVICE_STATE.IDLE; this.castPlayerState = PLAYER_STATE.IDLE; + document.removeEventListener("volumeupbutton", onVolumeUpKeyDown, false); + document.removeEventListener("volumedownbutton", onVolumeDownKeyDown, false); //console.log('onStopAppSuccess: setting currentMediaSession to null'); this.currentMediaSession = null; @@ -786,13 +801,13 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', ' }); }; - ChromecastPlayer.prototype.volumeDown = function () { - vol = this._castPlayer.session.receiver.volume.level; + ChromecastPlayer.prototype.volumeDown = function () { + var vol = this._castPlayer.session.receiver.volume.level; if (vol == null) { vol = 0.5; } - vol -= 0.02; + vol -= 0.05; vol = Math.max(vol, 0); this._castPlayer.session.setReceiverVolumeLevel(vol); @@ -811,12 +826,12 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', ' }; ChromecastPlayer.prototype.volumeUp = function () { - vol = this._castPlayer.session.receiver.volume.level; + var vol = this._castPlayer.session.receiver.volume.level; if (vol == null) { vol = 0.5; } - vol += 0.02; + vol += 0.05; vol = Math.min(vol, 1); this._castPlayer.session.setReceiverVolumeLevel(vol); From 8f84b023aab98aa9bdeabe620c78e4b6b569de8c Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Wed, 3 Apr 2019 21:37:26 -0400 Subject: [PATCH 206/220] Restart needs to be called with ApiClient --- src/controllers/dashboardpage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/dashboardpage.js b/src/controllers/dashboardpage.js index 446a7c6d6f..79e5f8cf91 100644 --- a/src/controllers/dashboardpage.js +++ b/src/controllers/dashboardpage.js @@ -750,7 +750,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa var page = dom.parentWithClass(btn, "page"); buttonEnabled(page.querySelector("#btnRestartServer"), false); buttonEnabled(page.querySelector("#btnShutdown"), false); - Dashboard.restartServer(); + ApiClient.restartServer(); }); }); }, From 59ca1caf7d0a29da16883960d46269809ad58691 Mon Sep 17 00:00:00 2001 From: Andrew Rabert Date: Wed, 3 Apr 2019 23:01:38 -0400 Subject: [PATCH 207/220] Optimize images with image_optim --- src/components/notifications/badge.png | Bin 39306 -> 24382 bytes .../notifications/notificationicon.png | Bin 39306 -> 24382 bytes src/components/themes/logodark.png | Bin 48917 -> 39427 bytes src/components/themes/logowhite.png | Bin 50195 -> 39729 bytes src/favicon.png | Bin 9822 -> 7768 bytes src/img/logoblack.png | Bin 48917 -> 39427 bytes src/touchicon114.png | Bin 7010 -> 5701 bytes src/touchicon144.png | Bin 9439 -> 7479 bytes src/touchicon72.png | Bin 3962 -> 3524 bytes 9 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/components/notifications/badge.png b/src/components/notifications/badge.png index 372343f5c9c1678ac5e596cafa666a0299d9adde..656b516456f65c9b6271a83208182b2e8c526d72 100644 GIT binary patch literal 24382 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%0A&?cS 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 literal 39306 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%0A&?cS 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 literal 39306 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

g2a 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

*R-LxJq;z#QYE0Q z8N}cNBLVBtEe--eC+uT$)RsZE;(e=GY|;v{!(cNY!w7V&Jm^k3>|=Zvu|CU_h!@uB z`grhq(_W@!eJ4=k8O5nl#wz@Iq-(I=gES}sJp_CTW7KEPNONKniq-K%F#Pgqj06hG zEsO5h9SKi*5?`pUIDn&j5t0d+B9S-NvKiF-tG*0Ch`g7{3qj z0E84uwLyOkIuJ|n(v31Y#sFI4K_RA$mFsGPGDCfB_e8@~J};>KJt0n#kho4MyY-Jo z(`Vevqx*HWh%zHHPorPAY0n7MGXYqReLjo8Rx| z0`z+9hNl&*uwr3LU#X+n zb%6K49wo|>@w6X{(&WA5Wms{*+n*6%#XkI#GA-V@2e=cz%f{a-SXJtT6070NIydHv zp$YyGs2CN4yFnu#7}BsmWV))s4ik_wF*p<2`!r+C2pxcTrha{u^a5Axj`(NpuerO{ z!WQ>5DLN^bY7q;7HOxwQVA8Gh<3?4R5S^9&V?6?X+Mv+Ucjzc#CqRPAi8fvYVhC6R zu*gQbQJ}3t?XMzJJF3m4%G(0WH_97Pl!l%C(riP}Mb%rc>G*VxelND}| zr|Fad>Q&Ozl=m~5wDyhpf+lTFM!~fU zC$ob53Kveamsg0_n%-o3hI;pi!p-&UbXbQtRRRIf3Y!aRh>bwJNRwZ_@~-osIYB@; zum!~buPk?HQZNu?Oe9r|2Fq;v)VGXpD$A{A&|rM)5j9q?m)|-V*}htevGnY}8+ZV1 z0hv#IXv`Amb|@17jBtfWdJ3k+maZXz$qT|V<_k?o6aNDlN3b*2G%U~pMK%_*)E-dn zX1%#tc6+%W)BBHHQQtA^X3>2fomCA}@5U>^qyIKfc;j5-t2B zSWTVn+<3Ucgk67_#=?4t{yNzk-K}3@(r{8xBuu-pJxKJm#JD?7y62iB4Vu3=B!b#Cy#GcJfB#4?~Fb##^Rd#w2*h)ZFD3egbxnKlk#+h9$+AP`ka z`J`hIHZ2B0q}s8;JE35VHyJ)Pw+b`E7;a>tu6C{1bF4JBBREYkHyL|PB zbHj8Ya~RWW&1a2NH%Hqr0g-NxVgm6*IPwCt)T$s5^BSMDF&%P(^%TK+?jFH%LTlfn zkc0>U%X?wTvxX>^oqLzZ6z3t@@DUZ@3CeFoRi$gjE~VVqg&Qx9SZlUF%k5eh>|;a@{45gs_r>c;3lvyFXyt`IyU*|#yVF0=A*4wqm@`e zrEqOO=SbIDjBSdPEIGMcn7ko#7~R!q*iIm}maX6O-vVky6+k4JV3b+FJ^*uMOG z!&5CYkFS(F?+H{IGP!D-<0SLFDvXtI`0Q&9=x~Mv2DXDL&?iX;`!p%BHfN|&V{nMM zhs%Kk`m6B7?Y`z-Jg!-FRH+YSC%&C`klshzR~xkidb)gcf5t;?L35N}ag-ecty zB<=9c`iYZrmHO#q$FLOLsDeAPXAfjH=6*En#+@%9p_DG_Yr%sQs8P0%$PHvZMKwPJ z#H)fB7zJ}oF*at{iBx$9D#<&f4zD_<@LC9wiTm?Z##8%+8hT4L^t_#R9IEu$dT`d_ zWM*@6UbM#nw6j}_nSdn|n$v+&uKdyb5$mL4iTvDYtxD3S5m&7)PuyB&o`@Zv{3c$M zdCRDNy+oDopD-N~zjAW*=5kfsJ9pgt=><=mXL?a{PeA?Sto5urLoRE?XP^B9Ysk{LM2x- z)8q+?vw;B6#+{J)e7BvA(vslLY9C@=yrjc}n_NJ?^wj>;!?{*`XKjL$v&kF3;YX{&BybngF5>>cE1qtZ_5b($Mtu%Q{v=(HloT( QX$Hb24ZREbYBvM_53MZ{5C8xG literal 48917 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 diff --git a/src/components/themes/logowhite.png b/src/components/themes/logowhite.png index 58f94fa9898f78af1ea6c00f66cd6710c1c42939..560d910d74f696d9f4a5a8ff2e08aa32cbd2fa2e 100644 GIT binary patch literal 39729 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 OWvHjCpUXO@geCwqo=^S& literal 50195 zcmX_H1yodB7kx8ygAy`Giy+;g(jqEIGjw-%=SYbtrBc!;H8e;`4WNLuz!1_>(kL-B z|ML_7x0cJLYu&l;-h1vj`|Q2n3pJHTB!nobgMcL?4Ll?yRMnQDLaYQ*L1D5svmhUf+nh zefy+?13y>c1+9gC7b&&dlG~m8)KzYk~8;$R?;=0xiIuZi1Kr<8L9JoT5;Mx)!(&es%?Id z$p9ERcFUqmD8H?WITjiOem#@QN(va1|NAVd_B2CsKg@_(PUdim)1Uxgifib%q7LN+ zf!*<`KMq6KdeDO%NqaXs=j5or4>y0xLy^T6W~I}p?nJ`$lGt%?4}K+j4}(yB4T;;p zE-vB;&A`TKp-g%K#otFgRUqXd+-25J2~#@Q^NM?y-U3(KRa;w$so3_Sw@Ax=bm(qS zQj#;~>ZL5h+PIPW)qI9Cc^&yA$wZbCO!PGzw&>qJIzyb7KI4G`uVmr7YGL`E#;&Sa zm^VS#{|3GU2P$I7jQzPa>Q$dfX2^1&G7_n3oA{YtZdgPRGm6&joPB1%zIrb`3;vhL zo}dTRK8iUHU_+IJ9{?F<>b&s$%IU9Wf{lO#l72l{;w*NS@%FCk)#|&ih3RRDY|~W* zw!XEdk#$v*u`_ko(_0a_hRt#^rUA{m}YG%~)N3F(XNrFU#LUZyTMN zn5bo~L;ZWAGrzB4aa(e|dWbCg>ZMq~g>a5F?In3TbelpDZ({PENh!}6SwxNQOMW&Y z#{q(q?YlDt&th3G8MYJtor)H>(1+;#Arw`kSNA*)z}~2YMRXj4GazPZB@#zBn3(&d z!Go+vI8VFplj$Tyq~_IR9J0jL>R&+S)1pF{JrHI9Z+Nfu={6KGCY7lXb)UyEsRNR4u{30ki?u>Ut8M1FxS9$Y>K; zV0n9x_XMLs#L;i4poFG z&o!4*v2gVYR`)gvYn0Xh%BAU|<$ZKD1~LI;e*gSnmHR#fsVX-Fd0cDO7y{gx%-_jx zrVDVuDbFEnuszFYwh6m>Jvj?&>cr`@Hl;W!bl0%Tafy?@^LS{Tmgjyu@Bs789X6hjGcV@@0b?8Qke6YPn zSY35mh1bui5L)QnMi|LoAF6Zu{Lpji)a@5e^c|*l2lU z8lJynY{3jQ&sllSxDoqSDznA+7j@*?)jMP3R&$ssXZSQz4QT>X!!mJxk(IYX)o@nz zt*yQ|o)}kj{W!q(*9}7MwRc{`ct!SJZEsBg_{Qc83?Db$Ba96toYNAQ*PW<7NyEcS zxF4u}Z4n;6yQ0EVO@{pHGyC1Id@b_M)r4D_IfXB~XFI?Mphw2MBa6qy36Jg?9pdVB zX$j!YBB2sw(l*T3t%w{yLx|`z;GHqHHVRky25)`r^&? z`Io*l3rCnRJ!K+_u=vttXpwWO{G`qIgM(kmH~kIxVz1I{ft?cWuD~tc z_^iPj%}v#21pkIdfWs|4R<|{Cj*>jMUzFUMb8n89>XpKWe^dyKYyGJk zHz?@kLGt{?-(`QN!maN9&Kj1Kc^j1{(>)(2P-y9VvMo7h5u>(u7N+Nfx=oS|lS@42`jQ!o;By-A;oFAx|)3RsBK&-M}mcvuR zvBO59Tpt%6fdLG?ha`iKwsw8jPC8>#qy?YyW2@H0Of=^1zX*EJ*OxoALZ(|4W4m6! zL1=k5f{SF|?u6kUSFa7X)(EEk_*)qjFTRyw2NxID(aAw~K0~wpQ4b$&{?$!IOMt=q z)>B`zh;pTPzV}NPc;Q4Xa+J_NLE9hQa2mRQ zNeRs@ieNV(BhzcivJ~WkTlTJ0@`G87WMamL|D(f+vvEfQ%~a%8p8bjQ_ePr$pSa@- zIH`=;G?G|B(70GbjEsGkYd$;PDflsYa2 z*4pR!xneE8)b9`>;$Kf>kR zdVePfA`=#UIuNoDptOA3|1gPg#-+!GWbv%MS-iTceSeD3@V#wtTjo=%nArRsGltd> zyANDky$v+|a;j;9#hAgXGOhLgMqe&8W|ePFwEE5-Awm)zuWrStML1qDBaQX9&Ya@q zw3kwx`Th_M;_KTKlnPFWtNQMFG^!Ug2l@MA>Lli=%r$C-mZD-ac&4fV!CPF#pTU|u zU50x>?^*(4aD;=%bYN>Ys~t{^`T4%(?`+E?Ib^Pj-YGIjQ7KCAHGR)^=+g+q1; zK7guCu=jo{;ZyL-*{gSIEuC=i-JW@0!uLX?<5>l%->kNKXO)-BM0C57lvz6!E-)R6eBuk(;@3DetC-dAR2CO1kv z#DaWE7YtxGc20hUxqgaKT&Fl3yjp;MyQ%j5x}7PdPA*sTz41)Qharm#$gIa*CP zip61j;@s0iIL^gsSkCR?a;H&*@KB4qkD~Xu&4IGdVaB@9Sg&O-XgoeDZtkv0HX=Io zy!z_5Zu6(0RU`w)er#zT9F*UwaM;uJ;OFuO@;)oiy&U_+pj5HeI6m7ux<9k;D_6>V z3fkF(rAeAo^?LfeMb2o>fn;hJ z#XnAXLy5P#-_Snwvf6?(;&^R;oi}pis?KmSgz0T{kI{)4^2wB|{W)~=IhP)hxmM}7 zZrl~4gObu3t;PHnu_Yy;eq(vhB1M{39{Qf~>`|SD9Ma~~Cb3_|pf9(OBRh3^^S&*G z5pg!}Q@uze`HZ_j&7zZ=^$Joa1qfm`N=)N&H|c z;R$^G7&+b)z8#t(Pu|liJT$aFvvLyISGMAo)z$hy;n(%O>VJEldZQ2N7MI?-SL*r%B;4+DlHpTEP?)t72S z|8Rf7)8CD~;~xT~ifAi=9n49tmuoy^WU>U<_EV0MPH^zze>+SVOI!ZQ32!}|E{9RM z?){II=VlykfSp`(9qc+FzWaW#QCaXQ+f{sUa0`{l65&dRq}bZCfqBlzSeGAHH|eBd z$JAB_HjbP3ET;#jkx8;^+4&S~VeE5_TYbbwd<>s1T=4^#DRh7K)nZpy z5uO(0VHch9s+3Q*yTYz&$U{^9;?BU6Z%N}^u4=#Pon&r-3u_csA?%EyReCl~R_~B? zU<4@9gzxdi2nz?*HMB5S7yC`O3J*6Me>>wthqMGE{}1`1QGy+?VR2tQ6ZGaaoOJ|w z-ZOz-qKu7jE{E$o$86jro@H;AU}l)i&#Y0S$I^p49lK$v)&(j#m%ztGq!pvGb z#@BR6$OtY(CX82=E}?|=AnsV$kxU(?d$YT$wMC~W%OMRS%K^k+LXN}`{o3O$lRov4 zTfwQOIZ9Hj!p(6RPDut2D7b2c)316#Ep1|JbQI}#KcrmC@R^r`TF3i3%@4!k zmx#yLWD7$*@@zHUZV+8ywe_>O8yc~12_BZs-j8iAR>d?+9X+y%Iz+7d0uE5d*1?*m zvTTd67YB6JU`Z%t{=vZY@wsh$ep0f411fpn5he)3wNP zqxuesaEbaynw^r5E0y!(@_Sh<;>)#k0T=%oE2_}85>57t5uZY1b9_{Hm$b2>$ zu%^?}c)ZD^<;?eRZ=N)pa(f2sSOQm5db;$Onw^tLe8LILsnP@km)+Ewm7igyZ>(N0 z)XgOwZA*&dQ#C2HWpW2trLJHd`E;x(*RS4prdmdjS0SG`@14Bi0Xu2{xCXoa!f+n+0JwUHc%5LG?l(b;vl{f z5L=WUys9i2On6oN1ugiC70(^Jf0T-epj!#robz9CS^!@;3ztBct5Odr?t^4YPS43~ zZ&cuARpUw1t7|C|j?3PYl+?|;Vap@tLbH)~;Tw7#0@Qom?CD(RPePb&GV=uK^;3^icr_GpL9=O}mk zmdws8Em-PYVL%`M;QP@*K73kxqpqc)<=pMnz*FVa$os^a|GFhgp=#t1D^_wkODKE4 z-rZkmEdkcvegk|#+DQQ|18ceTkz^So9zx%{4_LL0fS+50p0+c1(9Ad25^-<8om@77 ztr5cV)7z3*-o0C0rQZqcGy?uOYEMB}LJQR!kUs1A{_0ufkB3C7 zR@nZs4NyJ6wZAlox`48aGoEPWC<*r@SwE7iT)4z6h(^A3^0x53*)W~bv-@Nbqa5y)5T76PE929u3CY8*0_NB6`Y>^Zfo%3Ex^P(wg#8~EUkrxQ3y}%^L@lMervk$ zJGu{|Z#N7Y@o}=pWRC2tMvnB_|KNFaR>b?V9P22cH+yRlb5kf;|2vMLWRJ*$S)6ZT zy0<6Zx0LNscKqX2*uDsMaPI!hW@{FTwjv)*RqA;Cr&k#CjyVe)hdtczjeFAeozPKR z`P_6reYRB|M=8$ug35B;xEtE2E8>W0eq-7Pa$;Z+6d^2gs8-lGbEFnu$-E<(bVXql z#_$Ujw~HK_j4-Etk;oQ_Uw$h;;xp2uk=RK)?vcJ(AB>C2RwT28$oN~g)(K7a)iLWj zpevexs;&}z6P&ua;TLrIz({)EfrD)*Kq1a}cCzAM{5;`LfiHYqe6CY8FEcnSGoE5+ zyy0mvf6Lo0ebDGs0?GmwgKjn)BVl{*xrj(BuHl0^On_#>IcfIByRLTYTB<>xnADZy z7(LM-F+AoNwybT(hv&jw1xlW|XkgW_CiK4&vM?G>22&)4IHhIK;` zPpbVdwYBhoZe8i%IB>@WT4j>lV&a$cS}bN$jSdPsra|!1{EunQl@~~X=X@9$NQS!0 ztI6B~!Cp{=c=K!hP`+PEiyy3JBeb3k^4KD&@}U{;7g~o!ReH zM|@fx?vMufXx3H!$BAu)BFBo>#o%7iNU3aOHQehJa@%OTnN1e%14qAvACSU>9>WWY z*Y6;|S5618vg95tx&r$SZ~UskP z0ZZ4co|&Iz zE=_&Z;r%kx=*zPb{DAdvM{CmTF2MX=L{wDaO5r*gL;^p%%|ek7MGiE>4{lH#yBKWo z@WQtU=XHRS_-dhd(lumoUR~6 zEF+6u-42Jo+_lC%GK-2^yC+ZpIn-9e0N%MYXX!H&PIpek;LLJvq`UIV{7as$_Sj>P zvd-K{oV3z^kFGsXPPL1)15>sLs|odfKYjt}6JM@8!CUQj@u1=?3qj;)Z1`3gvKrDv zFn{x75EBv5LTnm*flKuYM-9G6R4>PUbN6iA>?o%#RUIxt4ffZDtZj%WC-TmQ%90K-TXGZ(fuf?k~z<(!`6zg5*`P5B3RjxnT`{v``DS=>kZu_CV^CH!+CU*7 zBySs+DX+KZm&=Lsz47WM{^0}q4bI@1^F^PL$U7oV>wUA*nhA!TuhALo1`)98p3Rpt z`!hn-O4vRmPxyGdT++c=zqhMU3{Kq(d5%(~Irz1e{*yNfnSyjKK&k>Mc&5GXI|bdo z@GawQW%7q$al?s^bztYHke)|Zchg5yfUIhY%_r@lvm-sdol&pH8D5>aLf@?x+Xf5{ z)3Z?{>ODk6AV4VL?ntqrE!=YG1{>DZlT*vIS_Yd5Y6=QIA8@vbo!pFa|pH zuSM%p-7`!-8kc8ZK92=dcrdr4a?SaR`xxkV&!i>|u~53Q9G8{5%5w&>4Nwk>s;cQY zn~eObIr?A_g^?805P_%alXgjN_eV6KI(bp_=jQKs6oJU8q2 zZ{oNsSAk@4W9QR7{es3YLaCQa3z`4C0LpU~7{%Xu?>Rh~Su`IFY)#pweCJipnq4HJ zG9)h|{)i27fL-Q^$v@~;p9Xrxo53j1`0(@Fh&o6g_O92*LmWGq?Yfp^;OGr9_Rb(F zh)NYz;TWu4I$-K;03UO+<~GTH$DMlSx!bcP|1poY-bqjAXUWa-$|1eGDdbRt*=T3)ocKZVrF@aQkvj9{!@OL~t^FMp&8TGH0*1r^;nw z>rEmRzcxAd%klm5b7B~7&3NRFtkm&M3lSYvGSp2iPI2wfl9F!axh=s{@1c{(G~(w` zh0#Upu>duyY+F@iZ7QF6Symb)q?CG?M3N`sz&a22GrY7~h*nkp4=4V_uy|rWI z?I*VMI}T4GAPL-*HgTCFdvlSR_^9-|l49fN-c(==S9-ind5&m6MD#rQbB|KYUXx&> z`{F9;r}gDUVx?>92QaKtgO~!~DMy?bLTW)OTN z(8Eb;eKbJU5b43!snHdxqqV+H;c;R}M(DYgSFD1yqz?ShTi5Z#d(gU*vAXfaoCHNl zetjGx&4F(qeE6Ji{T{<7j-dJ5wbVc0im$ zh9++9B_!RdT1uVG+*+INbn`tAuM?>y+i=BHij@VaoZlcux5HgELiUDU)5xRC6vq@5 zT(P<7jRK^9nnwvp-+`J8FW*7;=5H9$WHpa#@B+i(PW*8wN%jkSnG3vCzDE+xbO`$E z)1+YTXn3V?CZkP_;sFk+6X=|RQQ9)R_5=>>KzHb9NO!wJOdV;+q4;mjX{&89i3^ zr@1FjLND|NhGoRN5TAukL&Mafj$!s+4>vTD+k`=COv~s;EvIQQ7MSn6u@Z=eUFh_qFiB^8`c_ zjywS;wKA`nbrvRr=0R!W;Mi1&g^=%m6-7Zh%557D=wz=+Aap0m#jASf6!AUKnZu0O zI#G9VJ};oqyvao`*=ht+(fnEw6cFnfTz~y+JZ-T^k)wE;72Lh5mk8+=d4x?aIE6e) z0ZS&RQ1;b?j`24|V%M*O5f?z4bnCyVEZsu nrP|Lm;+(W;?C5M9@I&PI;0eWXTn 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 F_kWwDveW>)U@_asDkCU~0S)>(h zEDZo)wQxbiN&q0@76MdL;%`IpUvU7qG8RUJtv=A)dqueCTdl)9HkBIY#-tpT4Dm8f ztFO&(-xi0YY*3{?(%Xw^=YU%W z$6RZe)w}{My9SsTpoLxsPg#~l6zWxMfhXMmftAZPK-!Q+;Pq_^)eVMKVWN(x7~Rs} zXqzV`K!SeW%>2dX^l+`MjY*-^Wqb>rc@ZF=LsBT%_>Hs_smB zc!4*PabQP|A?u-RLnQRC2aTD_qR}L}&5Dn9;kEu2a%+;-c7b6VbmBaBL^#l6lkQXS zsB2>OI!QW&Hcc_HmtUukZmbCI}Q%qs!; zsMhbD#8;l1@`%3DjaX~XNcl3 zcAx+Yqm{S48tk^wp3eVq=-c5)4Hhr<_`TNJ+TmX%_MCLi+_+6y)5$gVAg2 zyJa5Qp|=nB!aJ0$cHx$O{9(F_o^ao5wSHX4Xrnm-`jP(vp#PJx46bDq-{Y-t47bdM zDJ$ZZ!M{4QEx43HSMLK( zl76>vt3EiW+Ms(mpdK@df0DF3ZYf-w{cqx?pI`3QRnVvXbsf3-fpwn6U?Nu9b7=!+ zEBs^g&eNyeh=emfpYhL;&ClIwGUdn;&c;U>InJG8kItE0e~NBkkICBInc{!XFuqu? zvJX$rkxd)y64PT%Ej!BGkmmY|;ht0(tC)15xpL5>OuLHTG03UhIpCP|B-`C2jr3Q3 zfWA2Awdc}qcfo*^zFR(+a$_?S`Cw*D_WakR@+ICN#|v^TYvE#V?T02_Y!>Nr zUj;}H$jBweMsGb=0(?gCC-Fui4>AsNRBs%@H$`myAsV8OT-= z;3qBxn$Vo5(L8BMw=DMzxqqX75$isDQ`Uy;BCt-+G9+@;W9nCfg4L8-6=5?kUbc#W zf_>P++uTu_g0vwkE1x}`lBdm<*(Z0Z9KsPVSQ1Ip|e&PPoO+XFkuVgB-Q@X|4M%fV7|5yEp{wCYegdJ<{psQXV} zy%<54g=1Bnk(*MgKZnxhfO!oDVQB)O;g%$sV`@BLjIYft`q#RoI*2<&DdM_?<3Rn8J-M<>6kYblm56&4M}%Z z^gW({!!rLrYX_j9S~>0MV&J!5X%W zwJ7~w&yUp~AZ&AhCgB|~coI~yw;I%PWN)LO>&NSP?*hzc=&dw%@4QRfgZ|V{=nWc0 znz~1qAQ5v~o=M`va1LVI#O3w9d&@x0l4zQT{rruFQPu)733HXydn)|Mp|Xm@&mAX^ zwmJO142}#eRK~7T)SEq*&Fs0t`niA#aO>SVGG4Xl!6Hle1q-_?WW2Kl6*ItQO6aNG zERS%2dT-SXO+LKV<(S*culpIu4s>1ovtL3ND#TYw;qP@k(E3y;A|16y2HiKN!NGF4 zNFdYvoj4Knv9^J( zljZfoG^GCvC$B&JIw;?%3jb|v=1V0br~&W(Qe`tvbNfU4BDw_{nX9zX44pjec=AaV zw|_BfHCo+KQhRrARvK)nWN#ckX>t!Bmn<=~U=aX#K23A-*SKNdL+SfX`}26Dtr~X= zv`1%=Lb(dy1+Dmqsb++Gd}T?w-b^B*S2HA!UxM0uecvp?Aza|Z`{q0>@c#;y5BAI% zH2k#CtXgbzz^X7$iHeLpO_hlzfx-Pc2Ybaa%{lfQ9fTjS!mqyL@p-ji$|;kp01&-M}FAmW8mEKU;_!8G}>M~KcAQDuWJ+Xsf`l6W7giRRpH z%}LH@sUy%yP55^HlX0OahmKp@VxQK?a(uw{vF{(TQa7&ptZASDC*B-+bA%EFwc-wPafq%F89V}Nop&03-btC1Ng<-GI)e1|O4XHyTBuMQ z80c+$^$eXC6sGZxN2USSyOdCKc*mD@c1QUW{(vPm_OnfrboC7tHgfeAWweg)`rbP_ zO?oI_M%HM{6)Khv;vML|4g#ai`EwVK49p!Ck;?TurQGpV!|SZ8#WP3unU9Bf3qRwg zJnomPHLRde_GBzh zn(gBW!4WPXZ(tQDV`**R>G8-VwLa1cl=gU-oCffGDpJ{j-k%y1lcdYGgxSP;n2=Gy zzz2pOu;hN1^Y=5tm=Z=?dspu|t_<#lrW94lLD#zuiJ5*JJQR<-nrR76f(4Y*bTDR% zuIISo_^A_0FFvgG5Xb^2q_g<@En1L@-X04Qg#Yf05+0uffi4}1X@C8=3Kxj9*An4R z$wb7McBIh8hp@sT+eftKAd$;+qwBtlw8_)Jn=SRr=~TJ!1v)O9&Tqx-*Q*bf73sCT zGfCK#wpD~u3|_)+71^{>%pp(E_-0{!?zc%4EB8P-COeS zeE>_-hNCj&>MI-62UG7u%YAicC{yH7R0Vr)Kpm80Tg`E%k|69ti=jG(<3**Q)y?&( zG1mNg7QE!`B+OP`oCwdOAZ9-%rz7}(8La`eCK01ZUTbu)D}K4(;#F0QCFl&*MMgmM zPpRJ%);1#*-3)Ugd;bc;tm=97)-K@no#%{|cXg|YBqs2tyEkN{I(ahqejI$h=L>R; z0j0LEVF&zQi&t0-jW4Lsvp)|e=23a@0gY0uTmA^%(bVEW13~5*M3c$}PfL8k*O)Y! z$Oj|8_es` zdqz6a_(k=&kt9Fs=b~EbjVY+;%viPd;BL@S5=nulJjuq1Lj>zcoAdh9eN*)0YXFsB zzNLo{JYowxmdxB!sJE{g&W=nIZ8g@w{>MFjMkLy5gD(P4qfI4|+4v`rS!~72w!;T{ zJ5&^mJMDX%o-_fk!fz0-J5*OJKo2Wp)K_izEt?5O6WLaYS!)9? z6@l7J#mqk1cnHgBL4vR{2W#Ud(loIA0|^#xZ!7i#1+u|{NGEV#Z$zb$b~R%UjVqG`oVx;wU-|eKq&4Zg$`=rFd%3WP%T24#1|zvwl??G$c8T9aQkZg(v#G zt(XPI6D*5$AJ5*c z>4)CFfPf}s9BMOL_pH?sm|&>+Nst*4Yl8X{TxJhF{0(Rt8R!QyzAcgK#(FU5KiTh$ zRoJ-v4(nTs)U(o~0qZv*{CPiP1Z28U`PNghgy9w^kVQs+R6!8_pAT-%Rq*K`Xg|PO zZhL%v^jx(@URKe!${u7TMetcWgRzrD+-mHMkAUTNlx^s_?J@AkBs4;XqjA`XDhD8c z>>ED(dr=FUCZuSt524b_`VpC$u^33iSGpc}f%pB@?7hR@a-r>#>3_!#E|71F`QjNvG#a+)bdLl;Z@AlOkZtl4@j1JwRS zmW$+Ys{V#5S?57kF#c@&5$|pmIzF0gqM5tx0j&AKYrGC8n@(H{7>0Y7;*?Mb#_ zP${x-s7nXDIm?Wc#YZgpXY~->LP|mR9?~c#H}x5Otiil?Ji}iqSFLVW7h8ka?%J;) zrvt5q)!%QC^GM7+H}ognpKpz!%dF2&jUkaRpsV;K2-GZL?ce;-8JLm;~a5Ifb~yMFb)j246FcDhq`O6zZ1g8FcjzyoW4gaxlr9!y6d63KpnE@ z&#nEh>;2!dD^;pLbcP@-{xtO2*fyDpQszD^mXHo0|2~&}&cPtua*9qdjxZlbNDX7&IB<#v@O3BstMEv_A0# zgTCK%-``(RzwNgVTZ6&4tFuDJU3JDVJkEuuFGgnHHFV?^bGO6-a% zyUygE4fnY{8<=rxuq?6lWq@Dqn#&+`;{exCHqId{essd+d+l%HyD9=5{CM>d=HSbhgP9y+iVUcsk8db(&%^2 zt41Qs}@(btqDyWc=0U0zm(c&;L*7dcz3RM^lDSY-N;PYmD9j596a+gmHl25LiCMOJzv6VKGgJs6a~N}M zTwQsD%87-*;TdG+1R=qdoPVf%-EXdha4IZ2*G_W>`*uj#W41K~`^G`3vON!Gb#Huk$N*}J z;LN3Pk6UtGK?bnq%xHf?Z-0<7_36Emr%)x2t>_t^{F}5dcD1yRy;>?+r(%Cx$B6!@ zNSnxAvy;NFycR$TWv?AsshO)$>=Yuyy?FsPeAWYJ(B_rKFvV_)ey%0S@k#&&DNrH2 zmN+kDxaIDIibo<*n=KSR4xIoERG<&hJh_RKhJ2Fw>L*|P$@%BdCYX$moT_3UK`Kg< z%ql+|kUp*4CQYwwJD^Ulw5ogVq$}!)4cf&GKi)_dL_N3lWlH@>Ei);?2GzYvv zAwy-s_b_e`k8Ga^3ce1fIN{%W=5U&A__DGw#1dz!WrMwC=UR}-sI)+TDp@yEz&5mV zcnN+0z_m)19Yz@U%ntm21^Ha5nuI-!M}F#X)SF2hAb<#1AK;`K1mmB&iX?x%-9X#qrOKP=Et+hM8EI>jg3~j{bAT= z2Q|1jVl|QZ@OPr!3DYFh^UR0?Wwyx1V>K&3JGkn(iH3U;8P=-~C__v%Sxww!F&2E8 z{w;?))f~bvxZ;;eWpcItvHpsYna$*n_2Zs1jxRJv4=24*Mp?oiN@dFu;a3U*?R7(P zL~jcUF5CbxKz}t=5pa5&OE^>HiWmKNzzI z5?Z6=jK;@R8^+nr*;4JyC9bx5?) z4Ui;^>Ye%un=&N9m?j6>ifIT*v+)3Z&_|-GCS+d&u00`Pn;JEOG3W-%cx04On9QPr zsFI`hgua0tQ8j>@Y*=F55;JVogTAxZ^xOEdw8x#VCKGG8P(m%y(X0`h$9<*37Wf1j zpJanBegJz$2aq(7^K(17cOZvGOb!r;q}-L1P+~MN0vt&1{D%%)Nz4ea&lXH2g%a%r zZ;$~DMEaQ(SLjzsWMs?^O#wV+^oNNO1_`&8d{)|M5_9)w{Au4@-9<4$07gN^@OB<4*?h0Yjc^;Gz~qa!Nf_kR z9hRC^o77_xbU*lPuC*x^BJpF9$v71i0+Ax_vA2XV)xN!=9(u-nShF{{%r5#(BlsAY^)Jef?!kR!CNSy#0W=d z3kGIrn%+~v!Mz0dQ7|L&5Etu8hxwp3L4KP6vhARVMZN=iaXBoq;8shL4qK~g$zLPUB5MPlfZkWfk( zKw$)i92gj;p85X%g6F*1=fyf_?{$6lUh7)d+DR5>1{awxGXnr{(a2EO5&%HdR}jER zPaPfwRC`hf{vbWOAS*x5pis8}58&PtzsDXTM!s%d9+n<%Ps031JTw465-`%eXZ>ms zAPSHPLNZ7m#zXzVD~*-DU+~#hmFY;zUL~!ILLTm$f(w+vv_Y! zFe)?{xm|n;|JnK#(W(6Nq-#H-!TG0q^8f!MA2;}vF@DnXtrzy%1a{rhCyA2S5TDC* zVt{&8ZC0)WXl371x7R4(L=DCvQkl_nc1wpT3b}MbB5VrWEUR4{F>r<@)2-DRs zBVVXMjfj2|FN0Q~nA^Y)a_B_+ z`HnBj40~CW*d3FxK4ZX0OZA*11j-|lE>%Ke$m(_jgTO%Z8OG-m>P8{bLls85wf_w> zBvcOf!4k8<2&RX-yl>!NwG= zAjlp1=D7fTYyqE=85ukC*E)yn^c@OiNm^AdTI?ii{A6SU(p32rVG(T&>SZ5XOL>~p z7;)Esj8c!FJ+iaqyh!HIlohI#(3}MM5Wy3o84S%R{(4#8Nb6Q1YWNHlr0BN=IZ)fo zZe-c5^#|a=oi)UDnxI8RQ1=gY~OyBdujj*>(=&+xn*u+cj zs}l@5KiIr@PKH_$mtJ@NtPJW^j05sot(1yTS0*&y;Vt{m?|w*UtK7N=q}dbhEAQp( z>aMAiq(w>X`{jN@NJS&%IBmGR8Z06K1y^1*f^D85_K-ch6lV><)hSg2qK5}8fdzl4 z#D;IRQ1qcX9hOrY|99);ok9sJM5Ia%~*QS!z@qAiEU`J1@aWV5@{| zi;q;OjF&F#te_yY6Z?iz9s9!NQz?>NRo>z3K=l||kKVTfY)AnOS=6?hYqTYHV^B}; z-0s@4jP|@72gs^H6lWt7NKY3O(vCyP3xHww^y=%an71-qB6OwI$L90+ymGEnjjZyg z&`Kk{zkD`K9Dwv7`Q?8p#mr1AW>uz%pXdZ!>_Y@1nX0->iIm(t@B4+MD52Qt2ylQK zO&pjDoOaCmx4Qe7lXEC%{99Bp$!D^MeZ%Tk9vuyA$u?i=5^$h=ror;=N~r~$3l5$} z@tFPG+OwkZIt+j|jw=W_Me;IA6$CzDpP!gC>8_+20pE^G9>2@vDnuu$4uYHw-OtO$fL-@a4uDF}=`z|2!~l zNkw8W&nl7B-jHGwopWj>ttAR%AE)MavlI?v{}7Yw61R!2OYb!8I8PtBfsN&<@EVby ziFw<=0YLA3r^b-d<$-L)BEOj|@+|HSCF7jr>`d;*Pq8GuavKlKd1?dKhCiu9zHUM` z!JMnGp-c52CeY)77Xz6MDaAjAndzLv)}YLEhM=qBB%44ePdPSbS3@=nNHu5DwPyb; zs|B#B6L`-nVGYGcVPiRw%7rkU)-UwL1WYBaLeWiNmOGok{4GH+5S12VM()-YemOquoL{^+0kVKV@3{O zm?_lW(YB@{?^!Q?$eO=YbLPHV=$fGA`s7;0lWbVf&W2Hb7cKB$UfAqJXx|MMKS92D z===Ve`_E@+nr-He)IE!`o2|QV^p*1fky?B;Ux@C~M)%y>o(DUnUc>s{Q$K{C@-a(YiS&&x@8miB-5a9`?&9{M3O zKJc3Xs|h5h^|}7?Dx23ND=8;dL3=Qoq1M>)oM6E`YZnW2zb8rA&*j4uHqI(UM z!5XYroWX8ddeLm7;q>R|&`10q@~%kakJe*j{v@oRCyC8V-BCiI(yqP!qjdS?-N6)I z^nll>RN+}5U!eQa@#{OGsTSI4T;1?v)}k{OUZk2DEK|k~!x{d3u}q6oCU*Oa;2$n# zHsH7!=2ZgY!=;wBPsX}Z^lb-Ehsz`m>?NN^E80_icw4fp+AuRF1z1R`&faQ6$6_Zv zU%*+f<#Dg7pf`v@SC27jf?*v-bZmgiRq{bLNlP--`A8|qdI%qZwf$I_kuKLD+JfzEsaU}J zHxnSu6qnk$g35NoN@#akNCDhsF7&Yc^yG_BP4B_WU}?dPM*Ct@J2+l9hPWQn0zi{7T| zMli34mgT80y&Nn2|6Dg9i&3|zZbE5P(a!rN7YK8)*oPzI%e(#9(}(I(%m|SryQdhx zl?0zUQ9GWo;}=?iUr-m3(~x8Q2^nzJ1>j1inju-&0qM>0Q(KgyQ%$l`SkR7#U42oi z7-{zta~q4|1wf0S>p8&_=|kupt7)y3gKM3T1HykVsloKP(I|Vh63z)$)pUW))<@nE zQ1_j)IHSYL*uPPo%fHk!9Nx4REImz5tO&>KBi zoQT&WZNr!02(ZY(;N9|+Ioj)t!NnUFKw97Ck;C6EM~Gb~{Is^iekm-$tDo>W2Zm#3 zc&F~UdhY+HDlVGXO^!O9g*2Vkm;q^5cCP*H-q};GdV~Fv{3=_S7q@?x{^DcQOaT`F zLTr2;NBm8yYD72)W~l-e)$QhV1n>Pz*g)6d1XHu$PE5}i6IsAgr}D3F)Y9&;OQ(|R zd`PS~r)wNQ^)69U58_sdtTSe`g@ZF&-(ZM}JRiE#V?25yF5Qbm6)k){6x-eg1O*>o zAEAa%P1X@aS|TAz*aHl-_!b&@?_4WuPi5wYv0;6#t+bGLuaR~yZ44J^z4mljL@*Y@ z#QrH?Aj)fEnH~{HQIKJ4e+y6M=+``?ehE_C&tF}wf-Oa-f8(*r*Ra216oJ))yiW#~ zuH73Sg+Yh7?FN2i8WJz^a0G9@^Upd%`E@FA4&1Z11dN9fJVQ?3I3`?@d+=-Fk?VPH ztI?bHe6?P?C1g6lm1&g9!AfO-wHxe^g3vxs6;(sF{qhS@$z}n3aepE!!e9E+>?lKD zpgYQ5a2OL+Q_7~?&e|QP8^F!~0iM4(Lo}F%brc>&`zKD}L4u+(iTSMFEe~n)hmYUq zajebKz)!WCt^W zwxbY*R}HX#)@TBhvJt+U0Cd*uoQV^D!vQX}+*;?#`}v9dAh7fa$Ytr)^j($yp}-4Y z%4evg^H8?lu#MTU9h^2nj?N(+?2tq$>2GOhH3jwi=X-9SRdk-fb{t~Cf>WTg*xf)g zTe@x557u-QHlVCZNmy?ajN9jn@DmclTQ_>1 z$%>>fi?COm*x_{K&e<`Lh3w@KLs+Q67HEjbIq6i~&zI?!g*}k3+AVfd6uB@?{uNB6 z2sD`e@^*9X5qwL9lzlf_&GA|G_sf=o&bLZZthfAF;qPp+&-VpQa+nPZz|uo(Ncvl2 zI(NP3rEVCn`yE)k!`-T-FO3Dmc1yue09P%MLQxN^8D5rt@mnQ1Q?!v`#bVpi>M4e}vu_JmJfRN3Cc3U@f=A89 z_L7%R3-8gEz5$EaNdjp;W$(^2elIg*l5`}<^jZol`H3%Pt}MUFWQ&aOf@bpz#97Rv zEb|tdb@q9g0Ja54&G8riET*ee=>Zn{=WP8UKgQ1~r>pUV**LCr%4V4J;88|cGuDO{ zNUt4!Jdfe{5vF*DnB{254U2i#6H{AME(N^ym`q|R`-xLYcXbOJz*;Dd*B z)wRGVJHuUV;+qMwp8W~=9l+NqDVDgE`W$Jg70}JhLkL|)P&1?m;eG}=7vqxs517)f z{zpB$S3LAq{k~kQDe$+<2;6|Wrgg-?ST-k&ScKRB6?(hx}8JvgE5=wNvV0wXJQ_ZWt zx5B((4#jhsWO+*CMpxA<$jrS;iWVRD?n~~MWPdP_NfN!@90)av*&SLn!OKpwWkm{^ z7G+SYV{~X_$SYZ(I9OSlG5)UWz!hubQxliTi<*F94rz}m=(MTcYfilISbbsdATu z60Fl%AMy*y0{1_|Ssevca48VNyn1|>g3DEUAes>hW6}EZTK}lA z@)h^KTDX(IWq|RhQ6ltot4lwL^nF)f7+*S#atv3l45d2@HSHk4+y`_J-0qwy# z&u*`haPGQ+P>|dquY6v@e{57|5e0j3y`>AZoG`PxpDYUu0OFWi?$FEGeFXNZ`|^J= z)I>Sbgv7Tmjyj!aOdk~XUn=ic$yUAy_|-uf<{@4J2+2Ep!9C>Q3a<{Ox}nH8jYks6 z+PV)wsHGskI*;p2VvWdKQlHhG&$T9-!P26^r}w;I*eIUq`Q?Ng{BgR!8CLnkqpv4LB`Nyl)Ka_E=ySVy0G{C; z;{M*U*WQf~ra>8!Z<5c!!h0n;;58{4|Hhjec84MK@)W~y^(C&$L@p;BLNlwJgh-ew z=1BdbHtRKSJ;numPBVu*6_ujI5_y4PY;F={pKUah?|naZx`~WyOF5m*{nJy{bd`+R z%XBeInjSyVA%VzAb+^Ti+H$wj?`4)J)mn`pKLWclmQIgsHGSAg(&)E(@w2kgdtpn$W} zFWo|mFKX&~{4Y}|8n0j*4%jmx#_eapbSr&JOj6|V z;qM(2lubFvtR(|r0>UNmSX4gD8ULu5K3ykfF)ti7cHR86H zG))Q2NMW9s#M$QbnjscG3u8BmBUY7c`Z1xc*J@?Jxq*oozvU0PvOwegM^}F=e<&fX zZFpI`twjB-bgykEC_XmTeSPS|hihO&3tRnjFWCxp7-AchYvWxBK>8CC;%O991`~bA7W&RWrx?~dcpPk=LyAsl9zG&=8@LhDkMvXc}OW%?)@tSg2o`*uJ#ULZ18QG@|1o1nZ%^v z?LO(1<)KvU+*o5R`OXsWMAPy7lF2%K zvr6{+mUTy+LFd*+pXbx(cWaJMmzSmTZ`bBElVyDr(6_qU+}(;Q=bkYpA)_OjL-<6v zfr@xQn~bId#@rFevlTu_*K^SK(mEK<(k#-`$EWFq+DTo}O!i`lu$E5d82P2MGh(OM z%LM1=5PS(GjrNf*4?!Kb2o&AW0|VG%7AWz|>7oQT{N;AW48z5s4AUUHQH-ueh^s$h z2TMmTbYH6fcinx3IJ&17tiM?y{dRbQmBQfGU6BEFKibaj8)zt-M?H~JQZHC&uhuVT z8=XiDvwcoypY+B{HPl)XFm$9RZi{=dcm~GISHR#sl04#>z9&#^mXgGaJ-}LG(pz5X6?uAjysd4CB9QKxnF@-VVQ?e`raOad%E{O|S1K{GIMu_|b-E37K>29)RAAA@P`HP&$MbZdv2+58(y?Z1Eh`db+-br2(s$c(; ztAMW})x;`l#e?ngFnID_4Cz?zJGF=NxQX?4WXFQ3=USr4Gtu;VFmTm@&~S7w0PM>A2y*Q!X4i-5yB&3#NI(zjMTOlq~~7W!s> z`IDwRF)Cez3DO;GOd;af;Oz2breX3Xu=zAQW56v`sJ%W^{h4;cr&qEWE@6KR@ckfo zUguJV8Bvur1TFk<+FIi6i0viA1I4+cdDJ&^5DgHNEVU}`=rE7W?gf;#Fsun*dE8Yt z-_q^y{xcb*W{5Nj4m~3(PY5=G?GzuZczTa!7~Rgbn&yN@vktqp8nkUCfwdAyF@o6l zwOb0cng$|Tl5a^~iw0lhGS37U6JTMR24z|zm~>bCLEMF=X4q-eo5==s20i0XtzE~i znN>IJU56myLcfU7hRm|9KHFGj0PY~h+^tcimUZkkQv8uVCg6W!wqE|klY5wQgNDAs zww|%7Yb!#pGd*Ae5J$ev!1#bBg_L4n89qY9GUw$W+YrHsQvI2Nv5~tWvv%8Z0?FHJ z)yZ+&dz`$$O_*8;+P8@Y{t{YEDH#faBCl03O!WI9uS|R?SqVFiw$I;t;wlU~44-&% zo{=jYMu$6R2!?)2`Te?td*8c1p9Ve-k?p_R^UEco8+_%!#G?-{^UsvQ)q>hvQqzCV zxVy*O(0AVUv*1R8|BnQ5ZmdO_A{Xrd3$Q6{lzANL0Hd2tP-(EcUgQ@!tnzt74G|H( zCD^8adv|5aN1s*yhLo++_pP7CfAQ^`?}RFP?x5G{;UQD^h|5tK*6gLv2G@Kdw!rWN z5dDvfo-V;MA7i+ddbe*CwWt&B{@#{#*4f(=H$6YayRGWF@&UsV)K1K8TxbV+9ChvU zSm32ECXW;swfUFhRTvbj_aV&{_v$N)ujPNM%DZUe_FfjXP`mj+e zZqd?f>c`ND)D7U`}Q4wsG{2te>Rq(_|FX*c;gZ+mb_LU(g&8D z{=GX}iihM`vj4tV2$lfH?9mOk36GYMUB5qM?^-|>d?YO+O5A=M8%Npb9!2ZcR)DjP zRm|x*VNsJxwg4kqgWrURUtuoVI{T?$HPlCLu0Xo4Nb9v+b4wjWO3Vr;wY5(IoF4IE zvu>2`X;cqhQ%LU+&9`S?GeEw^L)OJOTHaXQzE04~AWvX=6AblMo00O=LV{Vmy2rK< zD79QSkLwvsb@5+t$)>8c<(9U#SI+H?Jz+~`zb&}|R_J=7!&v#H|CLZHZ44)z;XU07 zr0-DD#6Huj7pp4XEoT7S8$7Fp zb&Occv>PF3e-l1IrVYht;h~O9oPO2nXIrMkg~3lU=__S$#quPi^C|NqPEeN}lQOOh zSWTMCxigT!r))OpCf{;Gj;42fAjvF@tO{J1>`Ie%HP!XBjy()pHA%YBLmux30L;i- zHqCaeV(QS*kZ#@^m%{~@_~X#f{GeIgVMvw^$pi8o-@_1xO|bowjsw>|jp=@!jjHUq zP>=u65)a|PO81kGST_#Jq-PcTPND2Q_)2Ik^-cuL@`AT&VtKRHa@5x$8Z(1U$nJM2 z&i*BGQqoYAotyNPi)2mqJ28;-IIH`-4Bs)APq=fl7d$KW-4SNm@ISEQThgS9CQ7>3 zWLF)^}flbI)f7T39A&!)!t~_|VbcZuVk+mU=Hw$h-C)lkej(a$ScM@9M>FOsd z6$&@w8z((+NSd2CLvA2wDY^xHBxK|I`kq4(YVI#iwn!3Z5DewXPW}(1<&?~NTvSN5 zKYT|YFD#qx4h40?1zbxDOoeDfq?;hEScGCy-I@pN<*WIYJEt>E>H_m!AAXC?tel{4 z{@Po+v|GrM92zV>(THUzNbDz5Th53{zn^{~Ii4+)%k7Ad8AuuAXvfY+Y#5?$w$Ibu zunsm&pHHm@2bdlNSw}4~Eu)Z(=VC1J2InWTm7~Kh) zF3~gAW+xbY_3C?a_NjZ1g8%2#@)>Wn4RlYmrno4E5A==pCV=^J7qk~sv50QY^m!LO zG;8+FOLRam;^~gfFVC}c7;(U9{4>E!lKN3`!Pg%zG{?hMFxGPQ?eORdSSmKct0$_a z`WOLQb`6=R&-eW;0D%(g!)-}d5x}aaz#Zq=_V5|hb;(*!XLPR$1j~sy!rVDCOs7&| zRE$dJQ&kdD6F)WBi0`!k!wY=pgP4w3RDZ1u0Vhmf3g%SB(OT0ee|6tP_u6#;9?xIU zS9a^+I6;f2_|`9It-f+0AkwUP_}c>j157y4T8qz8D|J~m}=pMra zp~30&S$9$90V$y+Z6EHLzxn^aN0lsZ eOMrpsf%sd#ku0doFzSUdz(~(bw_e-z_5TAaD2A2* diff --git a/src/img/logoblack.png b/src/img/logoblack.png index 3511abc23bcb27e20508829dce213c21ad3953f0..81a83818f817dc91853f5adc9c3e5f4e55744b84 100644 GIT binary patch literal 39427 zcmY&=2|SeR`~FCxgihJBr4(aLQAnats6;c2U73-n5LpKiO0tx(7G-OhiHyiP!XXV2 zWo+3hjFfdGWBcDT&iVe&@A#ZkpL*YCxtHs{?(2EpbI1IQG2a&PEeHgH@6^c?76`<~ zVg!OCkY^M8$ya;vas(ocdg_G!dH>#@{aha3|44E0-;;sS z=BPmNj7>q=ZTw1clmj1ku9VjtV%m-^7(W`MlN;`>te9qZNrkvh6mY;w5K6CyZ5X*v zGU?{~Y9{wcnRVzqxViIF7S2o1QS(8~Z{@f~W?;PtH|tUJkUK(0-E;Rbr#;X5Xe$(T zyo^a%Mn+dq#N!>)F(^5!J)HjosUgqutLP`EuaFlRf2Dn10y_ zm-})Dw2E?P8YtM8V_b%;H5?lxs}6XTX_k293a?(=lhZ`C!Opvq$jpuw6>^0ZKG^Ld zDfHAt2z$L>BytGT4LK##+`CKEGVNXXMEo86)pJ_3GjVR;7TzUm4vMknKju(h;(krf z=I)I+TAk&oM1o7}SfuV^mI$tZTw#a~CS?%g3$6|-vYriFvv<*u(y-yH*`J z`bs2e-6j2@n}r1W1Tex`44~2$!x-l5*<283@KX;9@s(0LLh;BqG8YiMUknT4U3Awf|r^kk7M;!%} zu2FWC9b`RiUN|t_F?0FP)7MQVXiRxLWkFDf8S<5sC32&g6w$vtHWbr1JM@(muE(l{ zDHp56R~0Lpkf8*^T7dH?(p{UoqDRc`A!{hnLbI3Bg;7tn?~H{wq!y58rSVg$6Z9aX zMBn@toA%g+HkVL|zu)kvNU@&&Ol;@Azg_VZhDf>}M{zAAS76aq*9?n8zcv0zu8kCc zN5bwQ5;Zcg&kJhkNS=?sq`oGzR@PqeE0#FZ%`46}(~ zc*)fC*2(dMZ@9(|u^!kH0e4AzD$ylprtCT$q#io5#!h{9 zOLg-5)VzskRwt6U??WA!q(W&BIdLozg+BE32I+E*?qNOFlWOPOj$F*%zN(-=jwv8h zwV5HL?>SRqMAG=rhwp1{6ke@C9)81mP}EjX_bNP?|KRXN0-?AG=}ag&_&!_`fA+q; ziyWpu#*cJ$<;uJC(YxW-S(XeVB8QLfLk_p$L@@JqZM^jXTFe0}TKmEVBFSD1ON;At zoqhMnz3=Q+*67yO008!Tk;7f1DrBkymJrHVIfhOo>{*+u^C4(F`gLG&oQBE@J;{3b zZC%-q4_5t`v$x|9E0FKEfaz+h4AE&s(pTfbVl=ox=$ief)!9Z=*MJu5g~!1U2y|t+|2zOSwW?$kWFl`1V09T z5=Hy*6Gbc40QbhdDOg#)$$B)*+YFs^=nT5fQp*anxSkK0egt2z4r}cD!EL;6`g2=M z$N^V^PP1NkyIc``?$7J@CVx^Sh$QcL%2OV^7a%u#s!- z+pNvp@Pp22kq3Z7qmI~lVQVbGpMhUHB8?v`-TQ$gtN6ZmeA(?=RGXdxYl6qAOdVUl zN2FVhQ+rgF=u2<4jxs|YgEvo=;*u~KPv;i1uG;kldV0>Wo=yn9a*Zq=f>a=Hk;1nX zQITu(rQu~mTKG${W*arXkT)UHTAxZXwXNdKvaYxJP>uWh`%FUeFLW+se3U8R=O(p#pY@Y-gA zH6~&jmT(Dg2be4aUle$($)bG{r52dAo+TJ%kfBzQ_xAlOnYw6DeHYRxmzCKgBhRhIJ?`Y`hpq18w&B0za3!D4Yb@f!0 z$#!W%Aq-t6vKheZD^aOUR`D&0R`#X*>bW)3(*dkCAP`L>KWqEaD{FqnD9L3v%~nwX z$EcwfRu45|GH<;Kk0 zjC<@DLu}hLSQ(Pv?l%!iKvlQ<85Ilqy;qE|1=gE}uI z3V9KPFfNfb)EM^07dnJ3PdU9c3zpYq0(@GC?*jYenurU0AUxvOVBzG)SPg`^kNw z2Qg6S$MCyadgU65W=(r7FwkF=yC8=%VZVg<>GFZjY-^WQEFqG5R5*+VcNdab{x}aa zVzOgZ$*ZBg+|29c(h^t2**pPp%r)QD*DY}*lrRD-$<<>P+>&N(Wy?XP6rNCmvqQfT z=#KlnYRVV(oIOYP`wrIR=tx-9i#Uqnsv$bEfJ}>P{v+FrbwMo+8Jq21x9(4u{)F+> zd+$)mU2_I<1Xy+pJt&;01kP><1q-N>_f}B7Q!rbWF!$JCh4}9Md#KfH!OAW%kF^R4 zb&EE$AW4y&^h{Q98I?RpuY|#Vd15*T2H%CC>(}=TAxonpo6)SGP$nDLV*~V5%{&Pu zO$|^oLkK7vmvWMgc6zNT8<(LVPCP9C_5n%GlvgGry$JJn)UmX87T`R2a*|rkl*!-p z%KN`rGtnrr%>{PaO(DYUiJo1vZ5s$7$B+iE@%j*i>|G!pw;W&?UinpvDdk1zOkPGdgC!IoKha8( z%dK>ybPjV@)~jK%ip1`w_Jtz#=9;E0Aq1h7Dzz^tv>_P%weev8oB=jCaYX&q7xpxW z&v%2b4+|m5QnxA8*-!_%FF|8p4+{MZCS|al70${pC2Y@Qdy2<&d!8xxTKi{h_Pb&6 z*t^lstA50Tv336Ed@wttu;N8S^vHS+NH069SRLv8tiJwIt60BCC1419aF_;6y#*4& ziJ?1=qQ%TuVN{xb=lNGZN3E}~FFj}=S9aok5~TZyoT>MPa$v%ri zzZB71kG%W5eSJ=Xb)O)h0KtP{e@cy6@HgZeK>Y(pto?Ub=|u>Z5C{5pcSiq+f?;y= zTdR9T+-WxJuX-N8zVP$Dtm*hn1=Zvzb260W?f<2Eq$G?Kqm*(3`#$DE#&gZ}g=ReU ztud3Mt;C=@cH;f4Fsl$rvtyAa>-PTxQ1l{aih81r*FI4r*;qtXnyF){ygpsuV8zNu zuxRyJMY8%XBNkK{+=Il*nc7uA4mKX-w8J(8Iy`$_sniqtXnw`+>QZ9b3jL{7g~TUY+G5Rp(K=xe|{BeP|ojIpR@Es_e?ypNGe_m ze-@%Egkk^u2ffmwh>gQ>GFF(2SlU3T5a+f1g!N>e9w}9oZciIub*KV&S2k_&By?t< z_hhFr0KcIKhNF<&2xhr%B^X*Rvk>8$`VS_RJt-fvuyT>Bpl;EC6-l!u9MNM+ePze~ z9Y7s3a~FkzCUHlcLPS^E$Mpry9=Jg{V}&_uWQPq9!3?uavINc(Uqvc{O#ufM<_xSL zwUy$OY%~~BJJwc~F7xHYzb9}kZ z_Ph&Tk%?6N0#0gxU;=-4l)m`G@n9XB!c@(sbV`fMmkzx*9u!)GK5`HaIahe(kv}+xv09@GyBx~qQX?jNAtRGv*Tb067*W4 z&;rsuWa>l8hrUIn2Ol-AI3E347g;UxtR+yLKqNJ&2ua|r?jKQ=Xs$z<7|-zTWm7jq zSn%~OZdfJc<`O#|Sv5tSd9-FhADe%wCz5x`@o6*3aS;L?mJDgR7)uF)B!?nWOMUXm z%x*ml-n90HRDrQu7m$iAu=kO6KLVzvPrYU;>$D8=^_ku;w6)U!ZR>Sg-)PXjQ3$hi z{oPj$e4D1%`WVledVj=_Vjv7cfVDefuMFN-&h*%@WL@gtJ!**W3KGP;FCh2k6q2{c zQ&h7crtip;?M4g5E8d%}oA)i>r%JtN>dl*=V1p}R41zK_sqUST>0V3yjNVN)=W)8p z1N2Jub|`c#7Zo%iEpZ>DPrple^yV_%?7%7ZO2Wn>LwNv9T-Z!3l!5;qL!&h0n`l1l zThJ832>eZ<+GPKM>NSRRZ}{5^b9XO=+Utn(-MSVq{A2Y&EUPty(y%kVQcr9aspt(} zRA&~z3$YYx;Oq-pomM{e^`m)JWYMHqAVKId{5_UYo!jJ%rO~?@+S1uv6M^tKGZByx zL;9<&-OmaaAk0dx>?{$cJyzFiq>2*z{I8uN{L3X&l3tuWHd2g524?XNso#zdg3W-+^90t^#>Cq@sruvdYQcyNtbJG?mFKPYerAPPvPH({i4 zfKY7q$hzj)^cy6368OAd+9iNHz%Ou*^Jf(L9Y+D#&ITLQg;u)l6K;)ju;Q>7Ltz`4Zfq2C?ol2UfOo7-4MdWpE#=O z1FQNUXB)|W8g;himnhSf6Y=)*Z_N?h$kB$1<@4ny0!p7>d#5m_FlhN3i4HiqNcN85 zFn=z)xN&692-jqvu_)r1++zOnt_rI7$v^_(5~F_&saQK#XYhWmj>4DU>ZUVsUI=qG z9~SgS7*kt7mIb^ocTXxgUSIy@_i^AnmTietSD~P=FNF^;|M-+asFDATSiG-Tb)Unt zYL*|HH>-t>p5+}m*I@MBYr&n87i@ufwoLRcdwvj6w*ONJ`E`>;2b5P?qd|NDYpYNS zznr1DnnhTLPCC(`Sg#?Qp>*Hb4+TBQ;aQ6>mUgKXV`+B<6apK5^r~f%RF7@6m06*c z6pCaVXkRoY@K(RTzxUZzMa_mI*}<5!F_m(J3@Ic3mw#RiDLSWsT#BoUr6{(y@e;yv zrjX<%iq{uZlzTor_vgd z(|zi@0q5I=@vG>?%nOPM)znbM!UKqH;TpdmLx^896v8~W$9}l6S&bXZ8;2f*lbnqww0b6_AeG2#BxxmYq zM=ny@Lx+!q?I1KKMGM*HeMt^{&X0KXDF`?1KKVP`>^MxgiJT z!gnH;5?xJ=5y!_@P=B2CA>?iC(~6;FUKE!`APOx#VuRa0M;FR#8l`Uy^Zxd$IVnic zmUA(2R*4fa9!n89bNf&z--pqPd7lc1;ul zWXf*xw!++K?RC}(`ZaBz_9fFbt#K3Ltx`i{(?zO&{_howqW$F7SneT|iGGnr@|wkc zP6WX^>jo%`L=qiXlQ>KS|L(TJ@}9=U(5|J_96QiPfg&sWC%P zrc-+lH2Az;$a=Be-Q~-i!4#2X4h0XI3|4D}D-a8bc7rOUg!VWgUyLB3j0A1#-41zi z9COI}nsRM&)fsv*=*k-2G?@$|Cw?Rk6pm@cUCoyvSf%*nYO)D55EeN}yq_WMkGeZ; zb=e0E)NRw-^K;%KKG*{F(*Y6Q&p70Z<%`3fe-m$@>8tGb;&^-SL;u*)JxX*9m3bmf zed6M{19s&{MdZr9GzDZzG4}*=qInp|GcuNv;(-0&omOWCP^31Sh-0Y`?b9DKtstJaBtfD+(s*m zoME!Xb9S?!bG@H(Bpq{zVZ-@2Q8GUmT_h!TKJyBKszg-^Q?9mY;x>~&JRXZ2+zO?J z)x-is?VYRg1d7{su-kQU_DPLp;{4+U6dDDTBnvtu+NWkEdsn{DccMWF93P(@E$BX# z8|@nXxFx$~gZRf9WV}M@nOWlzc}~QGPOWO!d_{6LAOH(xNFRYvxAD&Vx(`NmW z;So?i`Ne-Z$$Jkr=*&N>3~bDGFiuf0!$RuZEEPkYGkd)|DMi6m-b%5a`XFZh zWYuv_g!!F$w=5!Q8p0X$1wF?!<)d9mkshV~sar?}ClZC|NW~deyd|6B4o*btVG#$@ zb%b{A4kEaUhN<6GC$4f7qNS`n>W<{wJRlXC{FrW<4$qXXId|Ge3WxOZ^* zXm)pMKpHy)e@J^~T-Y(XL>)}`kt9`}49M_KpN)rP)y~YTGEU2PA(Wdum^}*x>Nm$9 z@4l4yCfABkK^BqJW@auUO~-AoRXO#LZ+<#|;a)DV>sMxJ8jhzR4gSPaD$8U|-3GFx zHAg}`%Q!yr#GUg9ucCcE#M&aSe;(PYX!ES{i1jD`%;zL@NOm{pcjpnKk$d?!IOrae zHaq64KFWdk}e4}T4B3j36h4WY% z7u)|`@|yb0q>En_ zr=f_L(+S09-vaKw%gjG}^wMR{uvW9Kpjj*^aiC&BPX{FkN-hPIIGwJv6R%u)hQxL_ zU|#}LRJ5%nl8R&}s_bv1tLwg5>d!yQ@wjCJ8&=LLXyR_9HXeN3E!c7Kg}^b&ICnI$ zi8*tVRrU;GDS%IT`T=Wb??+70i_%ykLU$NGJk>KF#0%!O|lpApW@&Vo^+2 zRUBYtdmPKjpe-&8Qqyq>FRrKXtrSBSS8X&11zfwMhMKM+3>`p+ERZQ?`u;x^kpJwp z9s@MM<+z#c6w0`uo*#&K)>NUfxZXy{RWw~z2&Qf1AXrbp1YnAnUZ(<27Z#r;?U@!W2^)W+QKS17kzXZfx#r09mgllYV*XA&FUN(#} zVbGQQWWYYi9L$s#f#Ac?g)VJv=MvK0we>ttByC7ciml~By92F^DG-fTm#tF&Moi=C zp8B@*#uCFKh5Ux|!eLj6OKVOT((1V-@P$Jt+P+2$3m1jWMuSV<<-dfEBu1K$UjAi; zxw%d_2&dS2=v^u0K^1azxxDj#o`rhvUG8Q_gq@zzAaKd(Rgab49*cz9_Ae(Ysc8!Q zUXh$xqbU?AXL>`jaKnV(UxsMl^1ugJbSN$F^Ka23|BiUru4sSpz`=qA1sDw!oW`Lnw(0_HR|ZRd@ecc1tE zFQp$suoSu387m4XXhtqmVbtJH0{m8q^OoRgh+cs4n9#($;C)bsGhWozp^j&nc(cTl ze(Zgg`j^zN*BV0dPkpZYzr@ypxWVKX*^|0YJP#h{9%?k}GO2;~9N<_k5`Lx8mm<2d zET7Gm@9Xu(zkAWdJk64ESbZc&Vqe#)UbUc-n$-J)LB3d7jGnMt;%9mlk`5<$WO1fr!Q9xaTlUF;Y zD;kug@OVmm4Xdk+>i^B)3p#rB-!wsB(bZZe<>uwaMN;Kf<*({QFo>&{CYk$$FhMIu ztiBm9yFw%dv7pw#(lX(LP&^pmEUPW6KgtelApGZDel-t#x?aC_;XlLbY8z=;mK!X- zus9#`WUGRsRROxSpf2kU!l;li`>ArvBYkL%Vo2szn4We<>p_jpb5>icPZ`o2KnqEc z0m-p|+$suMg!hlAe*4D!8-MZqn=$~wGFjuTWn+=U1!PbNS@nSWcN=ew$7S)+LaB<@ z36@T!3*2^!9t2HWv)j`3qjU@7vk0{2G}S!A>qggt)%Z+lkVJ1+}|ze$*E--?^GxUa4|U>G}=c=v==NY)I?&rFmK&4ZS_X z`5!j}d}eP1u+9dE2x9avAt$s&M(#|ItJhq9h?Cu8+E9tUej`SMLWAuKK!v5nKJ3MQ z%PhxT`2RV=i=Z5SxpWJ(tw-Dx>W`VSfAnF{T&L5M2k!EThf_((MY4)5C^YPLBni$I zq7VIAZC--pPUrj|GXWCedGUIi5Cna@VKVSP7BJP(D`zK~)gdM>ZTtPW+&wDDf<1nL z8Gsp{Fh7j%xv2MgrcxyB(tlTUHIufY4myAo9qI1A7eun{D^=#Fpi5qStbg1MQ?pcv zx}ZC0G3uzxxNuD>r0CAZ{}|~N!PgR$YL;$&e-*~s&m6Gm zzWg!ayo3G0)qp2o9bM#Vs7O%1faeo*3tDxX> z06BvSAAOoT5)t+Jv%_H%D~w)zFoX+8Ew{w+p*D$m9s>tvZ+;jIs^<8Yx`Ba)ZfpFO z5yI#^0QrajEC9sUJU9U>{doD~M_i#;;8_?R&h~(7K`A@$(jyRu`;-}8^jqft`1}MH ztq0WK^_oX`A4gdj@&4@;5w)<^UCB#-QLr2|#QoH)AO5LMsz|Zf{!m6P>ejK7{#zTw z?4m-eS47^IEluy-Zs0KcHTT!aej(y98Lb*g+9T5RwI;nA#i0mfya;iaM=a0UXii^{-kkq_%o$f7#6WWLt7wvH9ml-d7uNwLVR^mWE{y zi>CUw-Q}eHRx(itFkV8M<}}TYA)7ntORa|WF{;~7C0G5`5N+0i)G^tE*>sBP|r&Z1RYQLiL(xo^BR^5@EoYJRd)O*0vz zRICy{GQG*;X8drWnnd6+4`=QA`f0^KTlWO>*F@}ld;nIN=DUv+?&r)~C7>4>{dmWp z9iw~b+-(LMDO}?>m0wAX)?W17pyqXhpy9B9YzFxZ^qb;#zf_g`d!Fo1tlx)=o|`MK zpE}c`l2SR66uN&`WpIeYnTF@5EH8~%#eXh`(=3Lhov!M6JM7KfwrX21I;J%+!i|Se ze>S>=mDZ^`9e%jgEIS33T2W_kX@gjUt)~J#QcKF@*yM4shfV5=Zq20QLklts&XN+G zu>lozFJB=BHi~B*u+3Kdo8@~Eu2g{=Xcvl zGzyFU`jqzzw_fzrvBo>+w&#NhI{9C3I0sDsJ^gOg9;;w9SR2fcJa353P@gDpE76&J zWP^`lo9@Dhpf!J={@&C>yCf@)S4FWFbah&xNtBPL-(w)vciwwJl+Blh=o{^%0%wqFH|#VNPlL&^!8T{!JHL!uN+6j$#x(klm0 z$rVkrYe-Xjmn)9y2ZQrp9p>s0>N-tD4t^KJ*jQn{aTwCBmggwm$nG`~5_a``Hf)}R z$$E2u$^Y2aWf2c&u>nskT}qhGol^ha+^pnqL03RWe{b1>(}{-;WOh#Qo)lT#603dv zScTf=@H1PgxYX}li5~G3-AM3~u}|fgNnd%Q88t=~Sv02}-L$qT?Qy!(W(l6yuEkTA zXFgQqObty2?4rk0CLFPDv6Qoa2|raU{wXYovDL3Aquwv)za*ujeP2Q8OmFUwC*oF^ zUbsMEg%Qu0a+<9&KZon@xq$mHAMPxgjG4)pOyIITW;4o3f5*a=zb%b!`V8-I`n-7H zq=>^!nPO2F#lW3sqGe{cpA-qsi=7Dg#BQPxGR3*{Wh(e#3f}11l ze$(EJm1-@w61{E7I1Ak3BY&H+eg*Oud#qL?$H90p%cC8mdR^ySuAIyeTm}pT;Eo~D z)ZGKGSfA`UrM9(RU2(Nz=fEbn@|wB;R_ryL+M-|aktbFgDUD_y?v+wPm=sNF98{E?NrXpgE+ju|4Y=AoEfL%Pur1;aLmVV)FL@D_) zidB4u$+4hY=lBscCTkkcHx*q(rq47-kg8j$g%uKp=m%Xu?TAV>MuQ7TGJ@IiEYyy@ zs1WaMq%d5Si$(PCby4}v@%BJVn352I*RO*$^(x%HL z*IQDXBI-JFh0!bBg+!$X?S2tNrGR$~?akK~_%wV(SULLR&zFtTH_a@tp2E#a$ruiH z^bg47WQP{D#Ap>Ct1#y)8g=sLa@me?_1xdIyeH4UMO?LjENCda5m>^>?DmB_J&701 zFW^7sH*M%2i~MB=&OrocJ+So3dwFqMo_ut0fvzJTqogK{KU7Aw5W$>D<9c(J7-YjT z1@T+QX7b~|T<-U6iZ2Fq7c#fT6}3<|o?7yeX(pwTH{|k887P$>yrXA5tz*^o1x`hq z^$nj-P<(Wl{6-LgfCQ%wGo{2|mAX3P0?JC7)TQuNcGz0ccl075>9OxgQu~y)Qi)G0 z;HD4I+(Pm}qrpB0tiE*E*=zh7KUGDeoYRDY`NIaozHoksC}0K2q6Et&jbXWX?L;j4 z3juQ+AnDXkA^OJHtF&BFMgeFJ^2J+?2KfreuQNqLoW|&tKW}ZH&`6NsGaA$=AUm-X z%aeif9nFpV{RJ^2GL|iXk9OEJJyjou7bEkW9)=wT-4eW=G6cG+CxT`AqioYZJ!WKB z`Ix(zRHjg@UBApU&)*e{=#BbyT>Jw23%D?}9 z=24dj!tUIR1}sfh7}4e@XB2^)4h9cj5`^>{mlvxfsY zd^vYqza(oCuG5WtFVV%_{zJ|ZAkX0=H$&qAzI>ZhOwM1LyU807jx`TD< z)4g4!EkBUW3gqP~pf+3|g97_ySu0gqyS_h|OC8avwo_{3gE|WDLw0zwN<$VIhgHBz{0(zGOD*r{Jn$N5%d>TB~z1U zzrnwQKj)C9=Unuia;6~4@cTL zHN%HlDZn!0?5?r8N*TYL&R5dSB!1Q6z`8YmMq69#;Xh;V6{gpMnbJ=2Jh-XlgD?Le zldM1F=S+Qk0;&a(q-<)OEUm26{GBxI9?3LJK5K5pwYK;!x zUXMPd;@~C@HLg`o_01Y}j>92p0?kUF)QJZK177JYB7CC!sh#Fi^;~{uYkxw>(fYx$ zhnWRIgp%(yQAs%7=J4(A@+a?&MLyooyy{ONbQ(35HQ701GUZ7DRiJ{ZiQ~EZ+x_N< zN@Z8}hP0BF9!#sSA(LxFMz?g+*ZJ8uJHBxH%IN+!rc>8F37L^E@^Ir*@rq5krr(A> zhe>>ED?X5n*@UIp)$5X;d=&et(eK26QecGh6Haj=L=dAsN>uVq9D$B(mA zv5C7m7{)NyYo-ExtcMsYQzz`YN4-TREKdH-h?>$5bP`uHbd!r%M+(rwZXadxkLFDM zSq$R!BPV}DngZK2R3Nt$k{_z`HX72R49LZ(NZR)oWBqnm-HkuSB5Uoi^H+0DLo+lg zHXpxkr7H#p!x?W~J$3d3cIYmP(5`qU%l#Wk>yXjeIWqcPb!gkk?_Z|cyZCFOR(1u< z$*SPZovI5}$VaNE;&io8hi4E%?u*m&V}0{gua=z!F&1#o2rj~TG4LLHn5g87=kLx4 zmDgn-(JESf_U?G6?b@|Ou7P`$;|vHYIHym-yg^j;clCSfvG9R^#&a64-0jmDw7H6} zgHz*UefYnwTer`a@;~>zHg(_sOGY<=>wQL6u3)?u99E0sxmSQ8g)pj1S^x-~QHca0 zt-lOuU03cZecXu`m_{moTT8-xOii@)%6larFN8jej-^EO&?~{wphImU(t^o^zYBFh}P zPmIbCUsYH(+5ZnV)$T15_h`|VvcEQnc%P#2T#gG!>CkMzE`Oi}MfWJGX9g2gmA1r? zoT;*=K){0-l5m+3Dzv!^N34XSmZ`O%pcUtWd~tp%oatyW`G3eZD-@f%oOl z6j~Wo9T2*T>b;-IFI{l*%~-`Ay{C-Bf|!gdxY7exMzxvzIZ0S_uG{BZF%!4s+{8+a z6NTF0<_l=aV@T8as%>&;Vg{}=)T^I#NMPG9wmI}RxXBCLSI~7*K6#w;$+z{^eLYx0 zgEzSDYo6V4lGE|nn>|b6&NEvdv6*Krq>ptL?$cadc+0f(g$k;LAZ8m}IR#~Q|MsDK z98XGgU-q=7TU@^j_v1Vm{n12HpHCrK;!x|0Yg6PzmKR*#@+WK>HBcXwdB*8BwEGW- z&n0%ctmn)~#1&74J*H>Er;dr2DF(!lZcfA|OR^41!4yv%ay(Et zY|iE;^hLRooQ5Aa-`ChzpVFvvaYm43e^?(Y8q(auD|hvfH|E}qOpw4lu&6SJQ&u=8 ztZAAZM!H*%U#Yu)%ZMOhn<_StD}|4SQm7BT;^<2jM()pKR1qBD0gR}&Mtr3D2VCPt)zB9egFmUUYM(M+u=a7zX#>mM?&bhSR$wP4k3_bC$Rc*jD}5lJUp z#KCRh|0f(DXgU|xeo0O4MJqm{kO*(az2hHzb3A6|s(7ZubE?-mZV zy|}U@AjC?^6~0{4zvvrUGRyhXcT~%;d6YAoOeNnGto6Bh_E^Ph#818$Vpld?u{7ho z%8;y*z^`2$Z<^ilGr&RAVSEae3}@63hZq0cqI%nIT3U({|81N$?`978F+*P(z|!W! zvYNSA-rn~8a)QdQ@Me9fI)C^j<$2$h!wl2R8eIFoCP7fEw zTLGSEGLPC@-w%(S&48<`5}#1X*-aa+!ELHisE>h$$=NL?S%`qdU3K@594^sphC>?Y zkU-rDpBVc|^Z)fPeQep1f_;0UZDv~cWJl-|YntX7edElccKKe$cNI0DE+$EBp3SntH=0{XFUQ!_6ATlox-FmTG zsl4^a>PG?MS`Kg_A42E8+eD?OEfxGj*jhC+atbC|EJ=B=zUb{woxA!KuO-6&i-0Z5 zr_`=|`ZOJSwdc?VN5=UXEZE>4yG4YKe5V~&*~C%L$ohU=%j^a_?5PnHT9dBFE(*$I zGeDZ-bI7bWI30Hr-xwet0y$H0)iFx99b8J_gxy}3xGDilP*1^V$=KV-`_xHr>l~|? z*6@jV`(IOVzS&Uhy4pIJb%ne)?@zo6s6Ce$lCeN|0~5KXst-F|IqR%Ho8=JN@x5jG z&Cys&h8=bh`qxXgE*u919+~?-kQBK=o{O+_e*xve2VVDJNcv=nynyvV;w{~A65X5D zOzH|C2%SXBb=15ivlh`Q>b^FhE(DR+zvx z-d*_Pp?8f2Lno%_IzH2Moo9EI-X+{2%#V*JUabp1qLw$xpM+VBWeG4)FK?9^3Ll%B z*X#99glWZ^NxWe54UBp_?vA|0ZU4ny>|^t1bw@UJvfP@wgLbejB%RJ1>ba3OZw}7- z-q%g}-_F$uY=!f3PlhD4n~ztjwmp>P-E@|;e8V%O^Hg29P2nXznI z#RGHHSu~wVw!?n7cZDIjEPet* zuAW!h`oIiJD+k|knf)x^nrrH|&HBH^twRx#uTsWdzBs4p$D7r3jpradj#^q@=ha7F)oIcRO)p+VdUBUh`p$JVd3wYZY5(me_!sX zVzqG4yjdJkC8cz|Rxb8@n4 z|N3;cmcs)9E@+ti1L=M)aNIFcPCs$peFT+klsM9iN{-K&`ax7OOyr8Np^}zgq*L&B zD|mRrW!MOC1DKotNhEeXIYN6z^!b_<(&xg%IcJ{e-`n7t$uaG-oTJ8 z9g%*&;DG1=uoN$bFS<_IPCPf1laFveR}h0(RC|8; z)hn5WGcS*Fa?x5Luh$C64CBFFaQ8pErQ(P2&Wyrz%g`rIqK&`RiM$>g#_Oz|zU+H9 zBwN6}QTjjSeO%|SRQlrnlOjh;fX5X#Z5cwE!XarjqpL3bwVlM1rWf;Yjd}^$oCPon z@N0*Ce-n|FcZ)i4g76zLN@0otj~dk8 zo8z!ykXueI-fAaPq@tbv3vBp|upU1g{B_XDFQiint2uCIe;PT_quC4c&SeI^{Z)rX zUHJFWWQi~$>1;~@8K(aLpSy_SuLTiCL=zlKa@KO2+|aSLdX~k9lZm9GFV|}XaDl#L zjM^LLdtm%g^$EiSm8wl?RbiqS6JG2O>XEf+sI)I{; z^uo2Gbkz(iznd^OO`Ry5%bWH#b>H^2EFD)?9sj483+x^-ql{pafvSR@1z}SQUzNEk zx_2{0Udofbk!Koq)c*<+#yDv*uZ9rv0NOsGgkzM|QvP}5DeIS5(IFYm+t`39&Q6x6mJap(S z^Eff{JlO-g@+H85rxu0`NgRQqzDn2miE+_F5)F3sXbrz9Hb|@oLAtsbF6v+&udz5N zZ$auC+fPDs;;nEh(v8O1Uzk=scUIp~{kQf>5pmEP#gj3yDgQ12_^dp6^>HX6Z>?%u z6%=mKERnjePx9I}^I9bQMbW>;qUcJ{`Q65YO=3vah2&LR7k#~x&4nh#U$rOFD#Wfr zg572lyCh5sCuuu-R^2V?yW01zljU`FjIBLQ6p)ue=YaIEEhLkvCLoVO=>|fUWrc}i z3tArw4MRG0#KhJno$GytV@OwCuu=&PObHnLF?*L^=WrVK>TibaYSm&-W6>&2w+#DX zQ^K$*tN(1u(5<0na|lB+SRC&cHJBwLoU4|zOi3+dDarl^m`6)tO8{y1-;m9To1SwK zay-ggEuejbQVpjPAUrr?wNx_R%xJKup~dU(Rnq3!@Nd2*^!@|dFV84bc;wK

g2a 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

*R-LxJq;z#QYE0Q z8N}cNBLVBtEe--eC+uT$)RsZE;(e=GY|;v{!(cNY!w7V&Jm^k3>|=Zvu|CU_h!@uB z`grhq(_W@!eJ4=k8O5nl#wz@Iq-(I=gES}sJp_CTW7KEPNONKniq-K%F#Pgqj06hG zEsO5h9SKi*5?`pUIDn&j5t0d+B9S-NvKiF-tG*0Ch`g7{3qj z0E84uwLyOkIuJ|n(v31Y#sFI4K_RA$mFsGPGDCfB_e8@~J};>KJt0n#kho4MyY-Jo z(`Vevqx*HWh%zHHPorPAY0n7MGXYqReLjo8Rx| z0`z+9hNl&*uwr3LU#X+n zb%6K49wo|>@w6X{(&WA5Wms{*+n*6%#XkI#GA-V@2e=cz%f{a-SXJtT6070NIydHv zp$YyGs2CN4yFnu#7}BsmWV))s4ik_wF*p<2`!r+C2pxcTrha{u^a5Axj`(NpuerO{ z!WQ>5DLN^bY7q;7HOxwQVA8Gh<3?4R5S^9&V?6?X+Mv+Ucjzc#CqRPAi8fvYVhC6R zu*gQbQJ}3t?XMzJJF3m4%G(0WH_97Pl!l%C(riP}Mb%rc>G*VxelND}| zr|Fad>Q&Ozl=m~5wDyhpf+lTFM!~fU zC$ob53Kveamsg0_n%-o3hI;pi!p-&UbXbQtRRRIf3Y!aRh>bwJNRwZ_@~-osIYB@; zum!~buPk?HQZNu?Oe9r|2Fq;v)VGXpD$A{A&|rM)5j9q?m)|-V*}htevGnY}8+ZV1 z0hv#IXv`Amb|@17jBtfWdJ3k+maZXz$qT|V<_k?o6aNDlN3b*2G%U~pMK%_*)E-dn zX1%#tc6+%W)BBHHQQtA^X3>2fomCA}@5U>^qyIKfc;j5-t2B zSWTVn+<3Ucgk67_#=?4t{yNzk-K}3@(r{8xBuu-pJxKJm#JD?7y62iB4Vu3=B!b#Cy#GcJfB#4?~Fb##^Rd#w2*h)ZFD3egbxnKlk#+h9$+AP`ka z`J`hIHZ2B0q}s8;JE35VHyJ)Pw+b`E7;a>tu6C{1bF4JBBREYkHyL|PB zbHj8Ya~RWW&1a2NH%Hqr0g-NxVgm6*IPwCt)T$s5^BSMDF&%P(^%TK+?jFH%LTlfn zkc0>U%X?wTvxX>^oqLzZ6z3t@@DUZ@3CeFoRi$gjE~VVqg&Qx9SZlUF%k5eh>|;a@{45gs_r>c;3lvyFXyt`IyU*|#yVF0=A*4wqm@`e zrEqOO=SbIDjBSdPEIGMcn7ko#7~R!q*iIm}maX6O-vVky6+k4JV3b+FJ^*uMOG z!&5CYkFS(F?+H{IGP!D-<0SLFDvXtI`0Q&9=x~Mv2DXDL&?iX;`!p%BHfN|&V{nMM zhs%Kk`m6B7?Y`z-Jg!-FRH+YSC%&C`klshzR~xkidb)gcf5t;?L35N}ag-ecty zB<=9c`iYZrmHO#q$FLOLsDeAPXAfjH=6*En#+@%9p_DG_Yr%sQs8P0%$PHvZMKwPJ z#H)fB7zJ}oF*at{iBx$9D#<&f4zD_<@LC9wiTm?Z##8%+8hT4L^t_#R9IEu$dT`d_ zWM*@6UbM#nw6j}_nSdn|n$v+&uKdyb5$mL4iTvDYtxD3S5m&7)PuyB&o`@Zv{3c$M zdCRDNy+oDopD-N~zjAW*=5kfsJ9pgt=><=mXL?a{PeA?Sto5urLoRE?XP^B9Ysk{LM2x- z)8q+?vw;B6#+{J)e7BvA(vslLY9C@=yrjc}n_NJ?^wj>;!?{*`XKjL$v&kF3;YX{&BybngF5>>cE1qtZ_5b($Mtu%Q{v=(HloT( QX$Hb24ZREbYBvM_53MZ{5C8xG literal 48917 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 diff --git a/src/touchicon114.png b/src/touchicon114.png index 0e6afeb54394242f6c8dbf1c613b0e05d67beb0e..1a04cfa8779ab4bf19f4ee6cee1ee923d823c98f 100644 GIT binary patch literal 5701 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 literal 9439 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 diff --git a/src/touchicon72.png b/src/touchicon72.png index 935e2f702b9c67a9ae2a6e72ad33e6b82a7670f5..101143aa2d825015dc11800301a16f5afda19b74 100644 GIT binary patch delta 3523 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 literal 3962 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 Uez5yME&u=k07*qoM6N<$g4yhibN~PV From 18c61a81939c8a9c7987aaddbc1b4b383591adf3 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Thu, 4 Apr 2019 00:56:47 -0400 Subject: [PATCH 208/220] Update add server input type --- CONTRIBUTORS.md | 1 + src/addserver.html | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index bbdb64f7a5..1fe5f517ab 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -20,6 +20,7 @@ - [TtheCreator](https://github.com/Tthecreator) - [RazeLighter777](https://github.com/RazeLighter777) - [LogicalPhallacy](https://github.com/LogicalPhallacy) + - [thornbill](https://github.com/thornbill) # Emby Contributors diff --git a/src/addserver.html b/src/addserver.html index f87e889502..a17bbcf729 100644 --- a/src/addserver.html +++ b/src/addserver.html @@ -3,7 +3,7 @@

${HeaderConnectToServer}

- +
${LabelServerHostHelp}

@@ -19,4 +19,4 @@
-
\ No newline at end of file +
From 3b0b5228fe4b46221ba6cdf8e2de08f72a96e10a Mon Sep 17 00:00:00 2001 From: dkanada Date: Tue, 2 Apr 2019 15:16:51 -0700 Subject: [PATCH 209/220] deminify the installed plugin page --- src/scripts/pluginspage.js | 96 ++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 35 deletions(-) diff --git a/src/scripts/pluginspage.js b/src/scripts/pluginspage.js index 86f49d809c..e730da8773 100644 --- a/src/scripts/pluginspage.js +++ b/src/scripts/pluginspage.js @@ -10,9 +10,10 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" primary: "cancel", confirmText: globalize.translate("UninstallPluginHeader") }).then(function() { - loading.show(), ApiClient.uninstallPlugin(uniqueid).then(function() { - reloadList(page) - }) + loading.show(); + ApiClient.uninstallPlugin(uniqueid).then(function() { + reloadList(page); + }); }) }) } @@ -20,18 +21,18 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" function showNoConfigurationMessage() { Dashboard.alert({ message: globalize.translate("NoPluginConfigurationMessage") - }) + }); } function showConnectMessage() { Dashboard.alert({ message: globalize.translate("MessagePluginConfigurationRequiresLocalAccess") - }) + }); } function getPluginCardHtml(plugin, pluginConfigurationPages) { var configPage = pluginConfigurationPages.filter(function(pluginConfigurationPage) { - return pluginConfigurationPage.PluginId == plugin.Id + return pluginConfigurationPage.PluginId == plugin.Id; })[0]; var configPageUrl = configPage ? Dashboard.getConfigurationPageUrl(configPage.Name) : null; @@ -65,38 +66,56 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" return html; } - function renderPlugins(page, plugins, showNoPluginsMessage) { + function renderPlugins(page, plugins) { ApiClient.getJSON(ApiClient.getUrl("web/configurationpages") + "?pageType=PluginConfiguration").then(function(configPages) { - populateList(page, plugins, configPages, showNoPluginsMessage) - }) + populateList(page, plugins, configPages); + }); } - function populateList(page, plugins, pluginConfigurationPages, showNoPluginsMessage) { + function populateList(page, plugins, pluginConfigurationPages) { plugins = plugins.sort(function(plugin1, plugin2) { return plugin1.Name > plugin2.Name ? 1 : -1 }); var html = plugins.map(function(p) { return getPluginCardHtml(p, pluginConfigurationPages) - }).join(""), - installedPluginsElement = page.querySelector(".installedPlugins"); - installedPluginsElement.removeEventListener("click", onInstalledPluginsClick), installedPluginsElement.addEventListener("click", onInstalledPluginsClick), plugins.length ? (installedPluginsElement.classList.add("itemsContainer"), installedPluginsElement.classList.add("vertical-wrap"), installedPluginsElement.innerHTML = html) : (showNoPluginsMessage && (html += '"), installedPluginsElement.innerHTML = html), loading.hide() + }).join(""); + var installedPluginsElement = page.querySelector(".installedPlugins"); + installedPluginsElement.removeEventListener("click", onInstalledPluginsClick); + installedPluginsElement.addEventListener("click", onInstalledPluginsClick); + if (plugins.length) { + installedPluginsElement.classList.add("itemsContainer"); + installedPluginsElement.classList.add("vertical-wrap"); + } else { + html += '
'; + html += "

" + globalize.translate("MessageNoPluginsInstalled") + "

"; + html += '

'; + html += globalize.translate("BrowsePluginCatalogMessage"); + html += "

"; + html += "
"; + } + installedPluginsElement.innerHTML = html; + loading.hide(); } function showPluginMenu(page, elem) { - var card = dom.parentWithClass(elem, "card"), - id = card.getAttribute("data-id"), - name = card.getAttribute("data-name"), - configHref = card.querySelector(".cardContent").getAttribute("href"), - menuItems = []; - configHref && menuItems.push({ - name: globalize.translate("ButtonSettings"), - id: "open", - ironIcon: "mode-edit" - }), menuItems.push({ + var card = dom.parentWithClass(elem, "card"); + var id = card.getAttribute("data-id"); + var name = card.getAttribute("data-name"); + var configHref = card.querySelector(".cardContent").getAttribute("href"); + var menuItems = []; + if (configHref) { + menuItems.push({ + name: globalize.translate("ButtonSettings"), + id: "open", + ironIcon: "mode-edit" + }); + } + menuItems.push({ name: globalize.translate("ButtonUninstall"), id: "delete", ironIcon: "delete" - }), require(["actionsheet"], function(actionsheet) { + }); + require(["actionsheet"], function(actionsheet) { actionsheet.show({ items: menuItems, positionTo: elem, @@ -109,14 +128,15 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" deletePlugin(page, id, name) } } - }) - }) + }); + }); } function reloadList(page) { - loading.show(), ApiClient.getInstalledPlugins().then(function(plugins) { - renderPlugins(page, plugins, !0) - }) + loading.show(); + ApiClient.getInstalledPlugins().then(function(plugins) { + renderPlugins(page, plugins); + }); } function getTabs() { @@ -130,16 +150,22 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" } function onInstalledPluginsClick(e) { - if (dom.parentWithClass(e.target, "noConfigPluginCard")) showNoConfigurationMessage(); - else if (dom.parentWithClass(e.target, "connectModePluginCard")) showConnectMessage(); - else { + if (dom.parentWithClass(e.target, "noConfigPluginCard")) { + showNoConfigurationMessage(); + } else if (dom.parentWithClass(e.target, "connectModePluginCard")) { + showConnectMessage(); + } else { var btnCardMenu = dom.parentWithClass(e.target, "btnCardMenu"); - btnCardMenu && showPluginMenu(dom.parentWithClass(btnCardMenu, "page"), btnCardMenu) + btnCardMenu && showPluginMenu(dom.parentWithClass(btnCardMenu, "page"), btnCardMenu); } } + pageIdOn("pageshow", "pluginsPage", function() { - libraryMenu.setTabs("plugins", 0, getTabs), reloadList(this) - }), window.PluginsPage = { + libraryMenu.setTabs("plugins", 0, getTabs); + reloadList(this); + }); + + window.PluginsPage = { renderPlugins: renderPlugins } }); From e4590b489850ade770ba02024ffeece5e8f96124 Mon Sep 17 00:00:00 2001 From: dkanada Date: Tue, 2 Apr 2019 16:11:55 -0700 Subject: [PATCH 210/220] fix some broken and unused elements on the plugin pages --- src/availableplugins.html | 8 +++ ...ugincatalogpage.js => availableplugins.js} | 70 ++++++------------- .../installedplugins.js} | 6 +- src/{plugins.html => installedplugins.html} | 4 +- src/plugincatalog.html | 25 ------- src/scripts/librarymenu.js | 2 +- src/scripts/routes.js | 9 +-- 7 files changed, 38 insertions(+), 86 deletions(-) create mode 100644 src/availableplugins.html rename src/controllers/{plugincatalogpage.js => availableplugins.js} (69%) rename src/{scripts/pluginspage.js => controllers/installedplugins.js} (98%) rename src/{plugins.html => installedplugins.html} (68%) delete mode 100644 src/plugincatalog.html diff --git a/src/availableplugins.html b/src/availableplugins.html new file mode 100644 index 0000000000..ea1147fbfd --- /dev/null +++ b/src/availableplugins.html @@ -0,0 +1,8 @@ +
+
+
+
${MessageNoAvailablePlugins}
+
+
+
+
\ No newline at end of file diff --git a/src/controllers/plugincatalogpage.js b/src/controllers/availableplugins.js similarity index 69% rename from src/controllers/plugincatalogpage.js rename to src/controllers/availableplugins.js index c823d7c372..62131456da 100644 --- a/src/controllers/plugincatalogpage.js +++ b/src/controllers/availableplugins.js @@ -3,7 +3,7 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-button", "emby function reloadList(page) { loading.show(); - var promise1 = ApiClient.getAvailablePlugins(query); + var promise1 = ApiClient.getAvailablePlugins(); var promise2 = ApiClient.getInstalledPlugins(); Promise.all([promise1, promise2]).then(function (responses) { populateList({ @@ -33,19 +33,15 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-button", "emby function populateList(options) { var availablePlugins = options.availablePlugins; var installedPlugins = options.installedPlugins; - var allPlugins = availablePlugins.filter(function (plugin) { - plugin.category = plugin.category || "General"; - plugin.categoryDisplayName = getHeaderText(plugin.category); - if (!options.categories || -1 != options.categories.indexOf(plugin.category)) { - if (!options.targetSystem || plugin.targetSystem == options.targetSystem) { - return "UserInstalled" == plugin.type; - } - } - return false; + var categories = []; + availablePlugins.forEach(function (plugin, index, array) { + plugin.category = plugin.category || 'General'; + plugin.categoryDisplayName = getHeaderText(plugin.category); + array[index] = plugin; }); - availablePlugins = allPlugins.sort(function (a, b) { + availablePlugins.sort(function (a, b) { if (a.category > b.category) { return 1; } else if (b.category > a.category) { @@ -59,45 +55,29 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-button", "emby return 0; }); - var length; - var plugin; - var currentCategory; + var currentCategory = null; var html = ""; - var hasOpenTag = false; - currentCategory = null; - if (options.showCategory === false) { - html += '
'; - hasOpenTag = true; - } for (var i = 0; i < availablePlugins.length; i++) { - plugin = availablePlugins[i]; + var plugin = availablePlugins[i]; var category = plugin.categoryDisplayName; - if (category != currentCategory) { - if (false !== options.showCategory) { - if (currentCategory) { - hasOpenTag = false; - html += "
"; - html += "
"; - } - html += '
'; - html += '

' + category + "

"; - html += '
'; - hasOpenTag = true; + if (currentCategory) { + html += "
"; + html += "
"; } + html += '
'; + html += '

' + category + "

"; + html += '
'; currentCategory = category; } html += getPluginHtml(plugin, options, installedPlugins); } - - if (hasOpenTag) { - html += "
"; - html += "
"; - } + html += "
"; + html += "
"; if (!availablePlugins.length && options.noItemsElement) { - options.noItemsElement.classList.add("hide"); + options.noItemsElement.classList.remove("hide"); } options.catalogElement.innerHTML = html; @@ -145,29 +125,19 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-button", "emby function getTabs() { return [{ - href: "plugins.html", + href: "installedplugins.html", name: globalize.translate("TabMyPlugins") }, { - href: "plugincatalog.html", + href: "availableplugins.html", name: globalize.translate("TabCatalog") }]; } - var query = { - TargetSystems: "Server", - IsAppStoreSafe: true, - IsAdult: false - }; - window.PluginCatalog = { renderCatalog: populateList }; return function (view, params) { - view.querySelector("#selectSystem").addEventListener("change", function () { - query.TargetSystems = this.value; - reloadList(view); - }); view.addEventListener("viewshow", function () { libraryMenu.setTabs("plugins", 1, getTabs); reloadList(this); diff --git a/src/scripts/pluginspage.js b/src/controllers/installedplugins.js similarity index 98% rename from src/scripts/pluginspage.js rename to src/controllers/installedplugins.js index e730da8773..40de0cc191 100644 --- a/src/scripts/pluginspage.js +++ b/src/controllers/installedplugins.js @@ -88,7 +88,7 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" } else { html += '
'; html += "

" + globalize.translate("MessageNoPluginsInstalled") + "

"; - html += '

'; + html += '

'; html += globalize.translate("BrowsePluginCatalogMessage"); html += "

"; html += "
"; @@ -141,10 +141,10 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" function getTabs() { return [{ - href: "plugins.html", + href: "installedplugins.html", name: globalize.translate("TabMyPlugins") }, { - href: "plugincatalog.html", + href: "availableplugins.html", name: globalize.translate("TabCatalog") }] } diff --git a/src/plugins.html b/src/installedplugins.html similarity index 68% rename from src/plugins.html rename to src/installedplugins.html index 8209b60fd2..633df2df29 100644 --- a/src/plugins.html +++ b/src/installedplugins.html @@ -1,8 +1,6 @@ -
- +
-
diff --git a/src/plugincatalog.html b/src/plugincatalog.html deleted file mode 100644 index 53579d16a3..0000000000 --- a/src/plugincatalog.html +++ /dev/null @@ -1,25 +0,0 @@ -
-
-
- -
-
- -
- -
- - ${Help} -
- -
- -
${MessageNoAvailablePlugins}
- -
-
-
-
\ No newline at end of file diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index 9f21b81c16..bcfbf93ea2 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -362,7 +362,7 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " name: globalize.translate("TabPlugins"), icon: "shopping_cart", color: "#9D22B1", - href: "plugins.html", + href: "installedplugins.html", pageIds: ["pluginsPage", "pluginCatalogPage"] }); links.push({ diff --git a/src/scripts/routes.js b/src/scripts/routes.js index bd735877f3..070cfdc10a 100644 --- a/src/scripts/routes.js +++ b/src/scripts/routes.js @@ -284,15 +284,16 @@ define([ roles: "admin" }); defineRoute({ - path: "/plugincatalog.html", + path: "/availableplugins.html", autoFocus: false, roles: "admin", - controller: "plugincatalogpage" + controller: "availableplugins" }); defineRoute({ - path: "/plugins.html", + path: "/installedplugins.html", autoFocus: false, - roles: "admin" + roles: "admin", + controller: "installedplugins" }); defineRoute({ path: "/scheduledtask.html", From eb469bd1daabd1b6a561dc467f0a89574fee4a31 Mon Sep 17 00:00:00 2001 From: dkanada Date: Tue, 2 Apr 2019 21:54:00 -0700 Subject: [PATCH 211/220] deminify add plugin page --- src/controllers/addpluginpage.js | 133 +++++++++++++++++-------------- 1 file changed, 74 insertions(+), 59 deletions(-) diff --git a/src/controllers/addpluginpage.js b/src/controllers/addpluginpage.js index 32f71b8027..96e14f8819 100644 --- a/src/controllers/addpluginpage.js +++ b/src/controllers/addpluginpage.js @@ -2,32 +2,40 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e "use strict"; function populateHistory(packageInfo, page) { - for (var html = "", i = 0, length = Math.min(packageInfo.versions.length, 10); i < length; i++) { + var html = ""; + var length = Math.min(packageInfo.versions.length, 10); + for (var i = 0; i < length; i++) { var version = packageInfo.versions[i]; - html += '

' + version.versionStr + " (" + version.classification + ")

", html += '
' + version.description + "
" + html += '

' + version.versionStr + " (" + version.classification + ")

"; + html += '
' + version.description + "
"; } - $("#revisionHistory", page).html(html) + $("#revisionHistory", page).html(html); } function populateVersions(packageInfo, page, installedPlugin) { - for (var html = "", i = 0, length = packageInfo.versions.length; i < length; i++) { + var html = ""; + for (var i = 0; i < packageInfo.versions.length; i++) { var version = packageInfo.versions[i]; - html += '" + html += '"; } var selectmenu = $("#selectVersion", page).html(html); - installedPlugin || $("#pCurrentVersion", page).hide().html(""); + if (!installedPlugin) { + $("#pCurrentVersion", page).hide().html(""); + } var packageVersion = packageInfo.versions.filter(function(current) { - return "Release" == current.classification + return "Release" == current.classification; })[0]; - if (packageVersion || (packageVersion = packageInfo.versions.filter(function(current) { - return "Beta" == current.classification - })[0]), packageVersion) { + packageVersion = packageVersion || packageInfo.versions.filter(function(current) { + return "Beta" == current.classification; + })[0]; + + if (packageVersion) { var val = packageVersion.versionStr + "|" + packageVersion.classification; - selectmenu.val(val) + selectmenu.val(val); } } - function renderPackage(pkg, installedPlugins, pluginSecurityInfo, page) { + function renderPackage(pkg, installedPlugins, page) { var installedPlugin = installedPlugins.filter(function(ip) { return ip.Name == pkg.name })[0]; @@ -79,62 +87,69 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e } function performInstallation(page, packageName, guid, updateClass, version) { - var developer = $("#developer", page).html().toLowerCase(), - alertCallback = function(confirmed) { - confirmed && (loading.show(), page.querySelector("#btnInstall").disabled = !0, ApiClient.installPlugin(packageName, guid, updateClass, version).then(function() { - loading.hide(), alertText(globalize.translate("PluginInstalledMessage")) - })) - }; - if ("luke" != developer && "ebr" != developer) { + var developer = $("#developer", page).html().toLowerCase(); + var alertCallback = function() { + loading.show(); + page.querySelector("#btnInstall").disabled = true; + ApiClient.installPlugin(packageName, guid, updateClass, version).then(function() { + loading.hide(); + alertText(globalize.translate("PluginInstalledMessage")); + }); + }; + if (developer !== 'jellyfin') { loading.hide(); var msg = globalize.translate("MessagePluginInstallDisclaimer"); - msg += "
", msg += "
", msg += globalize.translate("PleaseConfirmPluginInstallation"), require(["confirm"], function(confirm) { + msg += "
"; + msg += "
"; + msg += globalize.translate("PleaseConfirmPluginInstallation"); + require(["confirm"], function(confirm) { confirm(msg, globalize.translate("HeaderConfirmPluginInstallation")).then(function() { - alertCallback(!0) + alertCallback(); }, function() { - alertCallback(!1) - }) - }) - } else alertCallback(!0) + console.log('plugin not installed'); + }); + }); + } else { + alertCallback(); + } } + return function(view, params) { - var onSubmit = function() { + $(".addPluginForm", view).on("submit", function() { loading.show(); - var page = $(this).parents("#addPluginPage")[0], - name = params.name, - guid = params.guid; - return ApiClient.getInstalledPlugins().then(function(plugins) { - var installedPlugin = plugins.filter(function(ip) { - return ip.Name == name - })[0], - vals = $("#selectVersion", page).val().split("|"), - version = vals[0]; - installedPlugin && installedPlugin.Version == version ? (loading.hide(), Dashboard.alert({ - message: globalize.translate("MessageAlreadyInstalled"), - title: globalize.translate("HeaderPluginInstallation") - })) : performInstallation(page, name, guid, vals[1], version) - }), !1 - }; - $(".addPluginForm", view).on("submit", onSubmit), view.addEventListener("viewshow", function() { + var page = $(this).parents("#addPluginPage")[0]; + var name = params.name; + var guid = params.guid; + ApiClient.getInstalledPlugins().then(function(plugins) { + var installedPlugin = plugins.filter(function(plugin) { + return plugin.Name == name; + })[0]; + var vals = $("#selectVersion", page).val().split("|"); + var version = vals[0]; + if (installedPlugin) { + if (installedPlugin.Version === version) { + loading.hide(); + Dashboard.alert({ + message: globalize.translate("MessageAlreadyInstalled"), + title: globalize.translate("HeaderPluginInstallation") + }); + } else { + performInstallation(page, name, guid, vals[1], version); + } + } + }); + return false; + }); + view.addEventListener("viewshow", function() { var page = this; loading.show(); - var name = params.name, - guid = params.guid, - promise1 = ApiClient.getPackageInfo(name, guid), - promise2 = ApiClient.getInstalledPlugins(); - connectionManager.getRegistrationInfo("themes", ApiClient, { - viewOnly: !0 - }), Promise.all([promise1, promise2]).then(function(responses) { - connectionManager.getRegistrationInfo("themes", ApiClient, { - viewOnly: !0 - }).then(function() { - renderPackage(responses[0], responses[1], { - IsMBSupporter: !0 - }, page) - }, function() { - renderPackage(responses[0], responses[1], {}, page) - }) - }) + var name = params.name; + var guid = params.guid; + var promise1 = ApiClient.getPackageInfo(name, guid); + var promise2 = ApiClient.getInstalledPlugins(); + Promise.all([promise1, promise2]).then(function(responses) { + renderPackage(responses[0], responses[1], page); + }); }) } }); From f83bd20fa9460d475387c400dd32074f745e17b8 Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 6 Apr 2019 23:07:02 -0700 Subject: [PATCH 212/220] deminify login controller --- src/controllers/loginpage.js | 152 ++++++++++++++++++++++++----------- 1 file changed, 103 insertions(+), 49 deletions(-) diff --git a/src/controllers/loginpage.js b/src/controllers/loginpage.js index fc8369c29a..b3e5c632cc 100644 --- a/src/controllers/loginpage.js +++ b/src/controllers/loginpage.js @@ -2,89 +2,143 @@ define(["appSettings", "dom", "connectionManager", "loading", "cardStyle", "emby "use strict"; function authenticateUserByName(page, apiClient, username, password) { - loading.show(), apiClient.authenticateUserByName(username, password).then(function(result) { - var newUrl, user = result.User, - serverId = getParameterByName("serverid"); - newUrl = user.Policy.IsAdministrator && !serverId ? "dashboard.html" : "home.html", loading.hide(), Dashboard.onServerChanged(user.Id, result.AccessToken, apiClient), Dashboard.navigate(newUrl) + loading.show(); + apiClient.authenticateUserByName(username, password).then(function(result) { + var user = result.User; + var serverId = getParameterByName("serverid"); + var newUrl = user.Policy.IsAdministrator && !serverId ? "dashboard.html" : "home.html"; + loading.hide(); + Dashboard.onServerChanged(user.Id, result.AccessToken, apiClient); + Dashboard.navigate(newUrl); }, function(response) { - page.querySelector("#txtManualName").value = "", page.querySelector("#txtManualPassword").value = "", loading.hide(), 401 == response.status ? require(["toast"], function(toast) { - toast(Globalize.translate("MessageInvalidUser")) - }) : showServerConnectionFailure() - }) - } - - function showServerConnectionFailure() { - Dashboard.alert({ - message: Globalize.translate("MessageUnableToConnectToServer"), - title: Globalize.translate("HeaderConnectionFailure") - }) + page.querySelector("#txtManualName").value = ""; + page.querySelector("#txtManualPassword").value = ""; + loading.hide(); + if (response.status === 401) { + require(["toast"], function(toast) { + toast(Globalize.translate("MessageInvalidUser")); + }); + } else { + Dashboard.alert({ + message: Globalize.translate("MessageUnableToConnectToServer"), + title: Globalize.translate("HeaderConnectionFailure") + }); + } + }); } function showManualForm(context, showCancel, focusPassword) { - context.querySelector(".chkRememberLogin").checked = appSettings.enableAutoLogin(), context.querySelector(".manualLoginForm").classList.remove("hide"), context.querySelector(".visualLoginForm").classList.add("hide"), focusPassword ? context.querySelector("#txtManualPassword").focus() : context.querySelector("#txtManualName").focus(), showCancel ? context.querySelector(".btnCancel").classList.remove("hide") : context.querySelector(".btnCancel").classList.add("hide") + context.querySelector(".chkRememberLogin").checked = appSettings.enableAutoLogin(); + context.querySelector(".manualLoginForm").classList.remove("hide"); + context.querySelector(".visualLoginForm").classList.add("hide"); + focusPassword ? context.querySelector("#txtManualPassword").focus() : context.querySelector("#txtManualName").focus(); + showCancel ? context.querySelector(".btnCancel").classList.remove("hide") : context.querySelector(".btnCancel").classList.add("hide"); } + var metroColors = ["#6FBD45", "#4BB3DD", "#4164A5", "#E12026", "#800080", "#E1B222", "#008040", "#0094FF", "#FF00C7", "#FF870F", "#7F0037"]; + function getRandomMetroColor() { var index = Math.floor(Math.random() * (metroColors.length - 1)); - return metroColors[index] + return metroColors[index]; } function getMetroColor(str) { if (str) { - for (var character = String(str.substr(0, 1).charCodeAt()), sum = 0, i = 0; i < character.length; i++) sum += parseInt(character.charAt(i)); + var character = String(str.substr(0, 1).charCodeAt()); + var sum = 0; + for (var i = 0; i < character.length; i++) { + sum += parseInt(character.charAt(i)); + } var index = String(sum).substr(-1); - return metroColors[index] + return metroColors[index]; } - return getRandomMetroColor() + return getRandomMetroColor(); } function loadUserList(context, apiClient, users) { - for (var html = "", i = 0, length = users.length; i < length; i++) { + var html = ""; + for (var i = 0; i < users.length; i++) { var user = users[i]; - html += '" + html += "
"; + html += "
"; + html += '
'; + html += '
' + user.Name + "
"; + html += "
"; + html += "
"; + html += ""; } - context.querySelector("#divUsers").innerHTML = html + context.querySelector("#divUsers").innerHTML = html; } - var metroColors = ["#6FBD45", "#4BB3DD", "#4164A5", "#E12026", "#800080", "#E1B222", "#008040", "#0094FF", "#FF00C7", "#FF870F", "#7F0037"]; + return function(view, params) { function getApiClient() { var serverId = params.serverid; - return serverId ? connectionManager.getOrCreateApiClient(serverId) : ApiClient + return serverId ? connectionManager.getOrCreateApiClient(serverId) : ApiClient; } function showVisualForm() { - view.querySelector(".visualLoginForm").classList.remove("hide"), view.querySelector(".manualLoginForm").classList.add("hide") + view.querySelector(".visualLoginForm").classList.remove("hide"); + view.querySelector(".manualLoginForm").classList.add("hide"); } + view.querySelector("#divUsers").addEventListener("click", function(e) { - var card = dom.parentWithClass(e.target, "card"), - cardContent = card ? card.querySelector(".cardContent") : null; + var card = dom.parentWithClass(e.target, "card"); + var cardContent = card ? card.querySelector(".cardContent") : null; if (cardContent) { - var context = view, - id = cardContent.getAttribute("data-userid"), - name = cardContent.getAttribute("data-username"), - haspw = cardContent.getAttribute("data-haspw"); - "manual" == id ? (context.querySelector("#txtManualName").value = "", showManualForm(context, !0)) : "false" == haspw ? authenticateUserByName(context, getApiClient(), name, "") : (context.querySelector("#txtManualName").value = name, context.querySelector("#txtManualPassword").value = "", showManualForm(context, !0, !0)) + var context = view; + var id = cardContent.getAttribute("data-userid"); + var name = cardContent.getAttribute("data-username"); + var haspw = cardContent.getAttribute("data-haspw"); + if (id === 'manual') { + context.querySelector("#txtManualName").value = ""; + showManualForm(context, true); + } else if (haspw == 'false') { + authenticateUserByName(context, getApiClient(), name, ""); + } else { + context.querySelector("#txtManualName").value = name; + context.querySelector("#txtManualPassword").value = ""; + showManualForm(context, true, true); + } } - }), view.querySelector(".manualLoginForm").addEventListener("submit", function(e) { + }); + + view.querySelector(".manualLoginForm").addEventListener("submit", function(e) { appSettings.enableAutoLogin(view.querySelector(".chkRememberLogin").checked); var apiClient = getApiClient(); - return authenticateUserByName(view, apiClient, view.querySelector("#txtManualName").value, view.querySelector("#txtManualPassword").value), e.preventDefault(), !1 - }), view.querySelector(".btnForgotPassword").addEventListener("click", function() { - Dashboard.navigate("forgotpassword.html") - }), view.querySelector(".btnCancel").addEventListener("click", showVisualForm), view.querySelector(".btnManual").addEventListener("click", function() { - view.querySelector("#txtManualName").value = "", showManualForm(view, !0) - }), view.addEventListener("viewshow", function(e) { + authenticateUserByName(view, apiClient, view.querySelector("#txtManualName").value, view.querySelector("#txtManualPassword").value); + e.preventDefault(); + return false; + }); + + view.querySelector(".btnForgotPassword").addEventListener("click", function() { + Dashboard.navigate("forgotpassword.html"); + }); + + view.querySelector(".btnCancel").addEventListener("click", showVisualForm); + + view.querySelector(".btnManual").addEventListener("click", function() { + view.querySelector("#txtManualName").value = ""; + showManualForm(view, true); + }); + + view.addEventListener("viewshow", function(e) { loading.show(); var apiClient = getApiClient(); apiClient.getPublicUsers().then(function(users) { @@ -105,7 +159,7 @@ define(["appSettings", "dom", "connectionManager", "loading", "cardStyle", "emby }); apiClient.getJSON(apiClient.getUrl("Branding/Configuration")).then(function(options) { - view.querySelector(".disclaimer").textContent = options.LoginDisclaimer || "" + view.querySelector(".disclaimer").textContent = options.LoginDisclaimer || ""; }); }); } From 38e3861e85be0d29e2dfdbaaed6c4120887fa7e5 Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 6 Apr 2019 23:18:47 -0700 Subject: [PATCH 213/220] add check for multiserver on login page --- src/controllers/loginpage.js | 5 ++++- src/login.html | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/controllers/loginpage.js b/src/controllers/loginpage.js index b3e5c632cc..2f396ff5eb 100644 --- a/src/controllers/loginpage.js +++ b/src/controllers/loginpage.js @@ -1,4 +1,4 @@ -define(["appSettings", "dom", "connectionManager", "loading", "cardStyle", "emby-checkbox"], function(appSettings, dom, connectionManager, loading) { +define(["apphost", "appSettings", "dom", "connectionManager", "loading", "cardStyle", "emby-checkbox"], function(appHost, appSettings, dom, connectionManager, loading) { "use strict"; function authenticateUserByName(page, apiClient, username, password) { @@ -140,6 +140,9 @@ define(["appSettings", "dom", "connectionManager", "loading", "cardStyle", "emby view.addEventListener("viewshow", function(e) { loading.show(); + if (!appHost.supports('multiserver')) { + view.querySelector(".btnSelectServer").classList.add("hide"); + } var apiClient = getApiClient(); apiClient.getPublicUsers().then(function(users) { if (users.length) { diff --git a/src/login.html b/src/login.html index 100dc7a3b9..c70064ed95 100644 --- a/src/login.html +++ b/src/login.html @@ -47,7 +47,7 @@ ${ButtonForgotPassword} - + ${ButtonChangeServer} From 85cffe7063f1ff90efa578a4572f222e3ed50758 Mon Sep 17 00:00:00 2001 From: dkanada Date: Tue, 9 Apr 2019 17:05:01 -0700 Subject: [PATCH 214/220] avoid element overlap with music controls --- src/css/site.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/css/site.css b/src/css/site.css index 0111b3823d..f048f4b8f4 100644 --- a/src/css/site.css +++ b/src/css/site.css @@ -74,7 +74,8 @@ div[data-role=page] { .padded-bottom-page, .page, .pageWithAbsoluteTabs .pageTabContent { - padding-bottom: 2em !important + /* provides room for the music controls */ + padding-bottom: 5em !important } @media all and (min-width:50em) { From 4e6820ca0dbc5ae5aeb21a8d2ffc01af3622130c Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 13 Apr 2019 17:34:15 +0100 Subject: [PATCH 215/220] Fix a deminification issue with the plugin page --- src/controllers/addpluginpage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/addpluginpage.js b/src/controllers/addpluginpage.js index 96e14f8819..0ecb65ab75 100644 --- a/src/controllers/addpluginpage.js +++ b/src/controllers/addpluginpage.js @@ -133,9 +133,9 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e message: globalize.translate("MessageAlreadyInstalled"), title: globalize.translate("HeaderPluginInstallation") }); - } else { - performInstallation(page, name, guid, vals[1], version); } + } else { + performInstallation(page, name, guid, vals[1], version); } }); return false; From bc64f4b99ecd3abec93f867b3c68c85450a018b2 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Sun, 14 Apr 2019 00:28:24 +0300 Subject: [PATCH 216/220] Readd Missing Strings --- src/strings/en-us.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index d39c7f9eae..c8731c7cea 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -359,6 +359,9 @@ "HeaderExternalIds": "External Ids:", "HeaderFeatureAccess": "Feature Access", "HeaderFeatures": "Features", + "HeaderFavoriteMovies": "Favorite Movies", + "HeaderFavoriteShows": "Favorite Shows", + "HeaderFavoriteEpisodes": "Favorite Episodes", "HeaderFetchImages": "Fetch Images:", "HeaderFetcherSettings": "Fetcher Settings", "HeaderFilters": "Filters", From 2ef711daf4f78b45ec531c4d5f0151e1b2a481db Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Sun, 14 Apr 2019 00:33:46 +0300 Subject: [PATCH 217/220] Add More Missing Strings --- src/strings/en-us.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index c8731c7cea..e6ffb12dde 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -362,6 +362,10 @@ "HeaderFavoriteMovies": "Favorite Movies", "HeaderFavoriteShows": "Favorite Shows", "HeaderFavoriteEpisodes": "Favorite Episodes", + "HeaderFavoriteAlbums": "Favorite Albums", + "HeaderFavoriteArtists": "Favorite Artists", + "HeaderFavoriteSongs": "Favorite Songs", + "HeaderFavoriteVideos": "Favorite Videos", "HeaderFetchImages": "Fetch Images:", "HeaderFetcherSettings": "Fetcher Settings", "HeaderFilters": "Filters", From e52c8792155e1c82aa9673b34d15ac449962173b Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Sun, 14 Apr 2019 00:51:41 +0300 Subject: [PATCH 218/220] Sort by name --- src/strings/en-us.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index e6ffb12dde..be851848ce 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -357,8 +357,6 @@ "HeaderEpisodes": "Episodes", "HeaderError": "Error", "HeaderExternalIds": "External Ids:", - "HeaderFeatureAccess": "Feature Access", - "HeaderFeatures": "Features", "HeaderFavoriteMovies": "Favorite Movies", "HeaderFavoriteShows": "Favorite Shows", "HeaderFavoriteEpisodes": "Favorite Episodes", @@ -366,6 +364,8 @@ "HeaderFavoriteArtists": "Favorite Artists", "HeaderFavoriteSongs": "Favorite Songs", "HeaderFavoriteVideos": "Favorite Videos", + "HeaderFeatureAccess": "Feature Access", + "HeaderFeatures": "Features", "HeaderFetchImages": "Fetch Images:", "HeaderFetcherSettings": "Fetcher Settings", "HeaderFilters": "Filters", From 076657bf96d5018589f05daa826c166f7e441a3b Mon Sep 17 00:00:00 2001 From: Anthony Lavado Date: Tue, 16 Apr 2019 02:02:57 -0400 Subject: [PATCH 219/220] Update the name in Manifest.json Updates the name in the file to read Jellyfin, and removes the previous comment. --- src/manifest.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/manifest.json b/src/manifest.json index ce66fa0f47..0ff87a92e5 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,7 +1,6 @@ { - "name": "Emby", - "_comment": "This should be Jellyfin, but that breaks apps...", + "name": "Jellyfin", "description": "Jellyfin: the Free Software Media System.", "lang": "en-US", "display": "minimal-ui", From 2ca5c4c10cd793d385f74c2d8be0f30c21638028 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Tue, 16 Apr 2019 16:08:40 -0400 Subject: [PATCH 220/220] Update location of edititemmetadata.js --- src/edititemmetadata.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/edititemmetadata.html b/src/edititemmetadata.html index adfd3568f5..86712a24fa 100644 --- a/src/edititemmetadata.html +++ b/src/edititemmetadata.html @@ -1,4 +1,4 @@ -
+