From 6bb1cf3554839b6605834686431c1788833099df Mon Sep 17 00:00:00 2001 From: redSpoutnik <15638041+redSpoutnik@users.noreply.github.com> Date: Fri, 8 May 2020 21:25:23 +0200 Subject: [PATCH 001/202] Feature: manually add subtitle --- .../subtitleeditor/subtitleeditor.js | 30 +++ .../subtitleeditor.template.html | 1 + src/components/subtitleuploader/style.css | 11 + .../subtitleuploader/subtitleuploader.js | 194 ++++++++++++++++++ .../subtitleuploader.template.html | 45 ++++ src/scripts/site.js | 1 + 6 files changed, 282 insertions(+) create mode 100644 src/components/subtitleuploader/style.css create mode 100644 src/components/subtitleuploader/subtitleuploader.js create mode 100644 src/components/subtitleuploader/subtitleuploader.template.html diff --git a/src/components/subtitleeditor/subtitleeditor.js b/src/components/subtitleeditor/subtitleeditor.js index e9bcc0bfca..4513d1d9d9 100644 --- a/src/components/subtitleeditor/subtitleeditor.js +++ b/src/components/subtitleeditor/subtitleeditor.js @@ -347,6 +347,34 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', } } + function onOpenUploadMenu(e) { + + var context = dom.parentWithClass(e.target, 'subtitleEditorDialog'); + var selectLanguage = context.querySelector('#selectLanguage'); + var apiClient = connectionManager.getApiClient(currentItem.ServerId); + + require(['subtitleUploader'], function (subtitleUploader) { + + subtitleUploader.show({ + + languages: { + list: selectLanguage.innerHTML, + value: selectLanguage.value + }, + itemId: currentItem.Id, + serverId: currentItem.ServerId + + }).then(function (hasChanged) { + + if (hasChanged) { + hasChanges = true; + reload(context, apiClient, currentItem.Id); + } + }); + }); + + } + function onSearchSubmit(e) { var form = this; @@ -454,6 +482,8 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', dlg.querySelector('.subtitleSearchForm').addEventListener('submit', onSearchSubmit); + dlg.querySelector('.btnOpenUploadMenu').addEventListener('click', onOpenUploadMenu); + var btnSubmit = dlg.querySelector('.btnSubmit'); if (layoutManager.tv) { diff --git a/src/components/subtitleeditor/subtitleeditor.template.html b/src/components/subtitleeditor/subtitleeditor.template.html index 7471972f59..b01942c995 100644 --- a/src/components/subtitleeditor/subtitleeditor.template.html +++ b/src/components/subtitleeditor/subtitleeditor.template.html @@ -18,6 +18,7 @@ + diff --git a/src/components/subtitleuploader/style.css b/src/components/subtitleuploader/style.css new file mode 100644 index 0000000000..c9d5eb980d --- /dev/null +++ b/src/components/subtitleuploader/style.css @@ -0,0 +1,11 @@ +.subtitleEditor-dropZone { + border: 0.2em dashed currentcolor; + border-radius: 0.25em; + + text-align: center; + position: relative; + height: 12em; + display: flex; + align-items: center; + justify-content: center; +} diff --git a/src/components/subtitleuploader/subtitleuploader.js b/src/components/subtitleuploader/subtitleuploader.js new file mode 100644 index 0000000000..bf3a8ca4b3 --- /dev/null +++ b/src/components/subtitleuploader/subtitleuploader.js @@ -0,0 +1,194 @@ +define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', 'layoutManager', 'globalize', 'require', 'emby-button', 'emby-select', 'formDialogStyle', 'css!./style'], function (dialogHelper, connectionManager, dom, loading, scrollHelper, layoutManager, globalize, require) { + 'use strict'; + + var currentItemId; + var currentServerId; + var currentFile; + var hasChanges = false; + + function onFileReaderError(evt) { + + loading.hide(); + + switch (evt.target.error.code) { + case evt.target.error.NOT_FOUND_ERR: + require(['toast'], function (toast) { + toast(globalize.translate('MessageFileReadError')); + }); + break; + case evt.target.error.ABORT_ERR: + break; // noop + default: + require(['toast'], function (toast) { + toast(globalize.translate('MessageFileReadError')); + }); + break; + } + } + + function isValidSubtitleFile(file) { + return file && ['.sub', '.srt', '.vtt', '.ass', '.ssa'] + .some(function(ext) { + return file.name.endsWith(ext); + }); + } + + function setFiles(page, files) { + + var file = files[0]; + + if (!isValidSubtitleFile(file)) { + page.querySelector('#subtitleOutput').innerHTML = ''; + page.querySelector('#fldUpload').classList.add('hide'); + page.querySelector('#labelDropSubtitle').classList.remove('hide'); + currentFile = null; + return; + } + + currentFile = file; + + var reader = new FileReader(); + + reader.onerror = onFileReaderError; + reader.onloadstart = function () { + page.querySelector('#fldUpload').classList.add('hide'); + }; + reader.onabort = function () { + loading.hide(); + console.debug('File read cancelled'); + }; + + // Closure to capture the file information. + reader.onload = (function (theFile) { + return function () { + + // Render thumbnail. + var html = 'subtitles' + escape(theFile.name) + ''; + + page.querySelector('#subtitleOutput').innerHTML = html; + page.querySelector('#fldUpload').classList.remove('hide'); + page.querySelector('#labelDropSubtitle').classList.add('hide'); + + }; + })(file); + + // Read in the subtitle file as a data URL. + reader.readAsDataURL(file); + } + + function onSubmit(e) { + + var file = currentFile; + + if (!isValidSubtitleFile(file)) { + require(['toast'], function (toast) { + toast(globalize.translate('MessageSubtitleFileTypeAllowed')); + }); + e.preventDefault(); + return false; + } + + loading.show(); + + var dlg = dom.parentWithClass(this, 'dialog'); + var language = dlg.querySelector('#selectLanguage').value; + var isForced = dlg.querySelector('#chkIsForced').checked; + + connectionManager.getApiClient(currentServerId).uploadItemSubtitle(currentItemId, language, isForced, file).then(function () { + + dlg.querySelector('#uploadSubtitle').value = ''; + loading.hide(); + hasChanges = true; + dialogHelper.close(dlg); + }); + + e.preventDefault(); + return false; + } + + function initEditor(page) { + + page.querySelector('.uploadSubtitleForm').addEventListener('submit', onSubmit); + + page.querySelector('#uploadSubtitle').addEventListener('change', function () { + setFiles(page, this.files); + }); + + page.querySelector('.btnBrowse').addEventListener('click', function () { + page.querySelector('#uploadSubtitle').click(); + }); + } + + function showEditor(options, resolve, reject) { + + options = options || {}; + + require(['text!./subtitleuploader.template.html'], function (template) { + + currentItemId = options.itemId; + currentServerId = options.serverId; + + var dialogOptions = { + removeOnClose: true, + scrollY: false + }; + + if (layoutManager.tv) { + dialogOptions.size = 'fullscreen'; + } else { + dialogOptions.size = 'small'; + } + + var dlg = dialogHelper.createDialog(dialogOptions); + + dlg.classList.add('formDialog'); + dlg.classList.add('subtitleUploaderDialog'); + + dlg.innerHTML = globalize.translateDocument(template, 'core'); + + if (layoutManager.tv) { + scrollHelper.centerFocus.on(dlg, false); + } + + // Has to be assigned a z-index after the call to .open() + dlg.addEventListener('close', function () { + + if (layoutManager.tv) { + scrollHelper.centerFocus.off(dlg, false); + } + + loading.hide(); + resolve(hasChanges); + }); + + dialogHelper.open(dlg); + + initEditor(dlg); + + var selectLanguage = dlg.querySelector('#selectLanguage'); + + if (options.languages) { + + selectLanguage.innerHTML = options.languages.list || null; + selectLanguage.value = options.languages.value || null; + } + + dlg.querySelector('.btnCancel').addEventListener('click', function () { + + dialogHelper.close(dlg); + }); + }); + } + + return { + show: function (options) { + + return new Promise(function (resolve, reject) { + + hasChanges = false; + + showEditor(options, resolve, reject); + }); + } + }; +}); diff --git a/src/components/subtitleuploader/subtitleuploader.template.html b/src/components/subtitleuploader/subtitleuploader.template.html new file mode 100644 index 0000000000..ef09775cdd --- /dev/null +++ b/src/components/subtitleuploader/subtitleuploader.template.html @@ -0,0 +1,45 @@ +
+ +

+ ${HeaderUploadSubtitle} +

+
+ +
+
+ +
+ +
+

${HeaderAddUpdateSubtitle}

+ + +
+
+
+
${LabelDropSubtitleHere}
+ + +
+
+
+
+ +
+
+ +
+ +
+
+
+
+
diff --git a/src/scripts/site.js b/src/scripts/site.js index c00169d224..d3a47031bb 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -799,6 +799,7 @@ var AppInfo = {}; define('recordingButton', [componentsPath + '/recordingcreator/recordingbutton'], returnFirstDependency); define('recordingHelper', [componentsPath + '/recordingcreator/recordinghelper'], returnFirstDependency); define('subtitleEditor', [componentsPath + '/subtitleeditor/subtitleeditor'], returnFirstDependency); + define('subtitleUploader', [componentsPath + '/subtitleuploader/subtitleuploader'], returnFirstDependency); define('subtitleSync', [componentsPath + '/subtitlesync/subtitlesync'], returnFirstDependency); define('itemIdentifier', [componentsPath + '/itemidentifier/itemidentifier'], returnFirstDependency); define('itemMediaInfo', [componentsPath + '/itemMediaInfo/itemMediaInfo'], returnFirstDependency); From 64da797e78e33e11eec8f087dcb2ec7dcb26dcce Mon Sep 17 00:00:00 2001 From: redSpoutnik <15638041+redSpoutnik@users.noreply.github.com> Date: Sat, 16 May 2020 15:16:18 +0200 Subject: [PATCH 002/202] fix code smells --- .../subtitleeditor/subtitleeditor.js | 6 +++--- .../subtitleuploader/subtitleuploader.js | 21 ++++++------------- .../subtitleuploader.template.html | 4 ++-- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/src/components/subtitleeditor/subtitleeditor.js b/src/components/subtitleeditor/subtitleeditor.js index 4513d1d9d9..350b95d669 100644 --- a/src/components/subtitleeditor/subtitleeditor.js +++ b/src/components/subtitleeditor/subtitleeditor.js @@ -349,8 +349,8 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', function onOpenUploadMenu(e) { - var context = dom.parentWithClass(e.target, 'subtitleEditorDialog'); - var selectLanguage = context.querySelector('#selectLanguage'); + var dialog = dom.parentWithClass(e.target, 'subtitleEditorDialog'); + var selectLanguage = dialog.querySelector('#selectLanguage'); var apiClient = connectionManager.getApiClient(currentItem.ServerId); require(['subtitleUploader'], function (subtitleUploader) { @@ -368,7 +368,7 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', if (hasChanged) { hasChanges = true; - reload(context, apiClient, currentItem.Id); + reload(dialog, apiClient, currentItem.Id); } }); }); diff --git a/src/components/subtitleuploader/subtitleuploader.js b/src/components/subtitleuploader/subtitleuploader.js index bf3a8ca4b3..09e45ba5d4 100644 --- a/src/components/subtitleuploader/subtitleuploader.js +++ b/src/components/subtitleuploader/subtitleuploader.js @@ -10,19 +10,11 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' loading.hide(); - switch (evt.target.error.code) { - case evt.target.error.NOT_FOUND_ERR: - require(['toast'], function (toast) { - toast(globalize.translate('MessageFileReadError')); - }); - break; - case evt.target.error.ABORT_ERR: - break; // noop - default: - require(['toast'], function (toast) { - toast(globalize.translate('MessageFileReadError')); - }); - break; + var error = evt.target.error; + if (error.code !== error.ABORT_ERR) { + require(['toast'], function (toast) { + toast(globalize.translate('MessageFileReadError')); + }); } } @@ -85,7 +77,7 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' toast(globalize.translate('MessageSubtitleFileTypeAllowed')); }); e.preventDefault(); - return false; + return; } loading.show(); @@ -103,7 +95,6 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' }); e.preventDefault(); - return false; } function initEditor(page) { diff --git a/src/components/subtitleuploader/subtitleuploader.template.html b/src/components/subtitleuploader/subtitleuploader.template.html index ef09775cdd..3f4944de57 100644 --- a/src/components/subtitleuploader/subtitleuploader.template.html +++ b/src/components/subtitleuploader/subtitleuploader.template.html @@ -1,5 +1,5 @@
- +

${HeaderUploadSubtitle}

@@ -14,7 +14,7 @@

${HeaderAddUpdateSubtitle}

From 11099fc41e9085f80641f3a7d3eca657f5cf2528 Mon Sep 17 00:00:00 2001 From: redSpoutnik <15638041+redSpoutnik@users.noreply.github.com> Date: Sat, 16 May 2020 15:42:39 +0200 Subject: [PATCH 003/202] remove block padding --- .../subtitleeditor/subtitleeditor.js | 6 ------ .../subtitleuploader/subtitleuploader.js | 18 ------------------ 2 files changed, 24 deletions(-) diff --git a/src/components/subtitleeditor/subtitleeditor.js b/src/components/subtitleeditor/subtitleeditor.js index 350b95d669..553255f1ad 100644 --- a/src/components/subtitleeditor/subtitleeditor.js +++ b/src/components/subtitleeditor/subtitleeditor.js @@ -348,31 +348,25 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', } function onOpenUploadMenu(e) { - var dialog = dom.parentWithClass(e.target, 'subtitleEditorDialog'); var selectLanguage = dialog.querySelector('#selectLanguage'); var apiClient = connectionManager.getApiClient(currentItem.ServerId); require(['subtitleUploader'], function (subtitleUploader) { - subtitleUploader.show({ - languages: { list: selectLanguage.innerHTML, value: selectLanguage.value }, itemId: currentItem.Id, serverId: currentItem.ServerId - }).then(function (hasChanged) { - if (hasChanged) { hasChanges = true; reload(dialog, apiClient, currentItem.Id); } }); }); - } function onSearchSubmit(e) { diff --git a/src/components/subtitleuploader/subtitleuploader.js b/src/components/subtitleuploader/subtitleuploader.js index 09e45ba5d4..9b9be4c753 100644 --- a/src/components/subtitleuploader/subtitleuploader.js +++ b/src/components/subtitleuploader/subtitleuploader.js @@ -7,7 +7,6 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' var hasChanges = false; function onFileReaderError(evt) { - loading.hide(); var error = evt.target.error; @@ -26,7 +25,6 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' } function setFiles(page, files) { - var file = files[0]; if (!isValidSubtitleFile(file)) { @@ -53,14 +51,12 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' // Closure to capture the file information. reader.onload = (function (theFile) { return function () { - // Render thumbnail. var html = '
subtitles' + escape(theFile.name) + ''; page.querySelector('#subtitleOutput').innerHTML = html; page.querySelector('#fldUpload').classList.remove('hide'); page.querySelector('#labelDropSubtitle').classList.add('hide'); - }; })(file); @@ -69,7 +65,6 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' } function onSubmit(e) { - var file = currentFile; if (!isValidSubtitleFile(file)) { @@ -87,7 +82,6 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' var isForced = dlg.querySelector('#chkIsForced').checked; connectionManager.getApiClient(currentServerId).uploadItemSubtitle(currentItemId, language, isForced, file).then(function () { - dlg.querySelector('#uploadSubtitle').value = ''; loading.hide(); hasChanges = true; @@ -98,24 +92,19 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' } function initEditor(page) { - page.querySelector('.uploadSubtitleForm').addEventListener('submit', onSubmit); - page.querySelector('#uploadSubtitle').addEventListener('change', function () { setFiles(page, this.files); }); - page.querySelector('.btnBrowse').addEventListener('click', function () { page.querySelector('#uploadSubtitle').click(); }); } function showEditor(options, resolve, reject) { - options = options || {}; require(['text!./subtitleuploader.template.html'], function (template) { - currentItemId = options.itemId; currentServerId = options.serverId; @@ -143,11 +132,9 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' // Has to be assigned a z-index after the call to .open() dlg.addEventListener('close', function () { - if (layoutManager.tv) { scrollHelper.centerFocus.off(dlg, false); } - loading.hide(); resolve(hasChanges); }); @@ -159,13 +146,11 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' var selectLanguage = dlg.querySelector('#selectLanguage'); if (options.languages) { - selectLanguage.innerHTML = options.languages.list || null; selectLanguage.value = options.languages.value || null; } dlg.querySelector('.btnCancel').addEventListener('click', function () { - dialogHelper.close(dlg); }); }); @@ -173,11 +158,8 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' return { show: function (options) { - return new Promise(function (resolve, reject) { - hasChanges = false; - showEditor(options, resolve, reject); }); } From b4e420df8f23259bf5b9becb095fa39b84d783b7 Mon Sep 17 00:00:00 2001 From: redSpoutnik <15638041+redSpoutnik@users.noreply.github.com> Date: Sat, 16 May 2020 17:25:50 +0200 Subject: [PATCH 004/202] es6 migration --- package.json | 1 + .../subtitleuploader/subtitleuploader.js | 323 +++++++++--------- 2 files changed, 167 insertions(+), 157 deletions(-) diff --git a/package.json b/package.json index 1e7ebfd0cd..61b67829b2 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,7 @@ "src/components/playback/mediasession.js", "src/components/sanatizefilename.js", "src/components/scrollManager.js", + "src/components/subtitleuploader/subtitleuploader.js", "src/scripts/dfnshelper.js", "src/scripts/dom.js", "src/scripts/filesystem.js", diff --git a/src/components/subtitleuploader/subtitleuploader.js b/src/components/subtitleuploader/subtitleuploader.js index 9b9be4c753..e631978881 100644 --- a/src/components/subtitleuploader/subtitleuploader.js +++ b/src/components/subtitleuploader/subtitleuploader.js @@ -1,167 +1,176 @@ -define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', 'layoutManager', 'globalize', 'require', 'emby-button', 'emby-select', 'formDialogStyle', 'css!./style'], function (dialogHelper, connectionManager, dom, loading, scrollHelper, layoutManager, globalize, require) { - 'use strict'; +import dialogHelper from 'dialogHelper'; +import connectionManager from 'connectionManager'; +import dom from 'dom'; +import loading from 'loading'; +import scrollHelper from 'scrollHelper'; +import layoutManager from 'layoutManager'; +import globalize from 'globalize'; +import template from 'text!./subtitleuploader.template.html'; +import 'require'; +import 'emby-button'; +import 'emby-select'; +import 'formDialogStyle'; +import 'css!./style'; - var currentItemId; - var currentServerId; - var currentFile; - var hasChanges = false; +var currentItemId; +var currentServerId; +var currentFile; +var hasChanges = false; - function onFileReaderError(evt) { - loading.hide(); +function onFileReaderError(evt) { + loading.hide(); - var error = evt.target.error; - if (error.code !== error.ABORT_ERR) { - require(['toast'], function (toast) { - toast(globalize.translate('MessageFileReadError')); - }); - } - } - - function isValidSubtitleFile(file) { - return file && ['.sub', '.srt', '.vtt', '.ass', '.ssa'] - .some(function(ext) { - return file.name.endsWith(ext); - }); - } - - function setFiles(page, files) { - var file = files[0]; - - if (!isValidSubtitleFile(file)) { - page.querySelector('#subtitleOutput').innerHTML = ''; - page.querySelector('#fldUpload').classList.add('hide'); - page.querySelector('#labelDropSubtitle').classList.remove('hide'); - currentFile = null; - return; - } - - currentFile = file; - - var reader = new FileReader(); - - reader.onerror = onFileReaderError; - reader.onloadstart = function () { - page.querySelector('#fldUpload').classList.add('hide'); - }; - reader.onabort = function () { - loading.hide(); - console.debug('File read cancelled'); - }; - - // Closure to capture the file information. - reader.onload = (function (theFile) { - return function () { - // Render thumbnail. - var html = 'subtitles' + escape(theFile.name) + ''; - - page.querySelector('#subtitleOutput').innerHTML = html; - page.querySelector('#fldUpload').classList.remove('hide'); - page.querySelector('#labelDropSubtitle').classList.add('hide'); - }; - })(file); - - // Read in the subtitle file as a data URL. - reader.readAsDataURL(file); - } - - function onSubmit(e) { - var file = currentFile; - - if (!isValidSubtitleFile(file)) { - require(['toast'], function (toast) { - toast(globalize.translate('MessageSubtitleFileTypeAllowed')); - }); - e.preventDefault(); - return; - } - - loading.show(); - - var dlg = dom.parentWithClass(this, 'dialog'); - var language = dlg.querySelector('#selectLanguage').value; - var isForced = dlg.querySelector('#chkIsForced').checked; - - connectionManager.getApiClient(currentServerId).uploadItemSubtitle(currentItemId, language, isForced, file).then(function () { - dlg.querySelector('#uploadSubtitle').value = ''; - loading.hide(); - hasChanges = true; - dialogHelper.close(dlg); - }); - - e.preventDefault(); - } - - function initEditor(page) { - page.querySelector('.uploadSubtitleForm').addEventListener('submit', onSubmit); - page.querySelector('#uploadSubtitle').addEventListener('change', function () { - setFiles(page, this.files); - }); - page.querySelector('.btnBrowse').addEventListener('click', function () { - page.querySelector('#uploadSubtitle').click(); + const error = evt.target.error; + if (error.code !== error.ABORT_ERR) { + require(['toast'], function (toast) { + toast(globalize.translate('MessageFileReadError')); }); } +} - function showEditor(options, resolve, reject) { - options = options || {}; - - require(['text!./subtitleuploader.template.html'], function (template) { - currentItemId = options.itemId; - currentServerId = options.serverId; - - var dialogOptions = { - removeOnClose: true, - scrollY: false - }; - - if (layoutManager.tv) { - dialogOptions.size = 'fullscreen'; - } else { - dialogOptions.size = 'small'; - } - - var dlg = dialogHelper.createDialog(dialogOptions); - - dlg.classList.add('formDialog'); - dlg.classList.add('subtitleUploaderDialog'); - - dlg.innerHTML = globalize.translateDocument(template, 'core'); - - if (layoutManager.tv) { - scrollHelper.centerFocus.on(dlg, false); - } - - // Has to be assigned a z-index after the call to .open() - dlg.addEventListener('close', function () { - if (layoutManager.tv) { - scrollHelper.centerFocus.off(dlg, false); - } - loading.hide(); - resolve(hasChanges); - }); - - dialogHelper.open(dlg); - - initEditor(dlg); - - var selectLanguage = dlg.querySelector('#selectLanguage'); - - if (options.languages) { - selectLanguage.innerHTML = options.languages.list || null; - selectLanguage.value = options.languages.value || null; - } - - dlg.querySelector('.btnCancel').addEventListener('click', function () { - dialogHelper.close(dlg); - }); +function isValidSubtitleFile(file) { + return file && ['.sub', '.srt', '.vtt', '.ass', '.ssa'] + .some(function(ext) { + return file.name.endsWith(ext); }); +} + +function setFiles(page, files) { + const file = files[0]; + + if (!isValidSubtitleFile(file)) { + page.querySelector('#subtitleOutput').innerHTML = ''; + page.querySelector('#fldUpload').classList.add('hide'); + page.querySelector('#labelDropSubtitle').classList.remove('hide'); + currentFile = null; + return; } - return { - show: function (options) { - return new Promise(function (resolve, reject) { - hasChanges = false; - showEditor(options, resolve, reject); - }); - } + currentFile = file; + + const reader = new FileReader(); + + reader.onerror = onFileReaderError; + reader.onloadstart = function () { + page.querySelector('#fldUpload').classList.add('hide'); }; -}); + reader.onabort = function () { + loading.hide(); + console.debug('File read cancelled'); + }; + + // Closure to capture the file information. + reader.onload = (function (theFile) { + return function () { + // Render file. + const html = 'subtitles' + escape(theFile.name) + ''; + + page.querySelector('#subtitleOutput').innerHTML = html; + page.querySelector('#fldUpload').classList.remove('hide'); + page.querySelector('#labelDropSubtitle').classList.add('hide'); + }; + })(file); + + // Read in the subtitle file as a data URL. + reader.readAsDataURL(file); +} + +function onSubmit(e) { + const file = currentFile; + + if (!isValidSubtitleFile(file)) { + require(['toast'], function (toast) { + toast(globalize.translate('MessageSubtitleFileTypeAllowed')); + }); + e.preventDefault(); + return; + } + + loading.show(); + + const dlg = dom.parentWithClass(this, 'dialog'); + const language = dlg.querySelector('#selectLanguage').value; + const isForced = dlg.querySelector('#chkIsForced').checked; + + connectionManager.getApiClient(currentServerId).uploadItemSubtitle(currentItemId, language, isForced, file).then(function () { + dlg.querySelector('#uploadSubtitle').value = ''; + loading.hide(); + hasChanges = true; + dialogHelper.close(dlg); + }); + + e.preventDefault(); +} + +function initEditor(page) { + page.querySelector('.uploadSubtitleForm').addEventListener('submit', onSubmit); + page.querySelector('#uploadSubtitle').addEventListener('change', function () { + setFiles(page, this.files); + }); + page.querySelector('.btnBrowse').addEventListener('click', function () { + page.querySelector('#uploadSubtitle').click(); + }); +} + +function showEditor(options, resolve, reject) { + options = options || {}; + currentItemId = options.itemId; + currentServerId = options.serverId; + + const dialogOptions = { + removeOnClose: true, + scrollY: false + }; + + if (layoutManager.tv) { + dialogOptions.size = 'fullscreen'; + } else { + dialogOptions.size = 'small'; + } + + const dlg = dialogHelper.createDialog(dialogOptions); + + dlg.classList.add('formDialog'); + dlg.classList.add('subtitleUploaderDialog'); + + dlg.innerHTML = globalize.translateDocument(template, 'core'); + + if (layoutManager.tv) { + scrollHelper.centerFocus.on(dlg, false); + } + + // Has to be assigned a z-index after the call to .open() + dlg.addEventListener('close', function () { + if (layoutManager.tv) { + scrollHelper.centerFocus.off(dlg, false); + } + loading.hide(); + resolve(hasChanges); + }); + + dialogHelper.open(dlg); + + initEditor(dlg); + + const selectLanguage = dlg.querySelector('#selectLanguage'); + + if (options.languages) { + selectLanguage.innerHTML = options.languages.list || null; + selectLanguage.value = options.languages.value || null; + } + + dlg.querySelector('.btnCancel').addEventListener('click', function () { + dialogHelper.close(dlg); + }); +} + +export function show(options) { + return new Promise(function (resolve, reject) { + hasChanges = false; + showEditor(options, resolve, reject); + }); +} + +export default { + show: show +}; From 7613dcfc1d863b450c5b482cdb50660850e4c9fc Mon Sep 17 00:00:00 2001 From: redSpoutnik <15638041+redSpoutnik@users.noreply.github.com> Date: Sat, 16 May 2020 18:02:14 +0200 Subject: [PATCH 005/202] Add subtitleUploader fr and en-us strings --- src/strings/en-us.json | 4 ++++ src/strings/fr.json | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 2014f2d611..683e97c676 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -301,6 +301,7 @@ "HeaderAddToCollection": "Add to Collection", "HeaderAddToPlaylist": "Add to Playlist", "HeaderAddUpdateImage": "Add/Update Image", + "HeaderAddUpdateSubtitle": "Add/Update Subtitle", "HeaderAddUser": "Add User", "HeaderAdditionalParts": "Additional Parts", "HeaderAdmin": "Admin", @@ -505,6 +506,7 @@ "HeaderTypeText": "Enter Text", "HeaderUpcomingOnTV": "Upcoming On TV", "HeaderUploadImage": "Upload Image", + "HeaderUploadSubtitle": "Upload Subtitle", "HeaderUser": "User", "HeaderUsers": "Users", "HeaderVideoQuality": "Video Quality", @@ -625,6 +627,7 @@ "LabelDropImageHere": "Drop image here, or click to browse.", "LabelDroppedFrames": "Dropped frames:", "LabelDropShadow": "Drop shadow:", + "LabelDropSubtitleHere": "Drop subtitle here, or click to browse.", "LabelDynamicExternalId": "{0} Id:", "LabelEasyPinCode": "Easy pin code:", "LabelEmbedAlbumArtDidl": "Embed album art in Didl", @@ -684,6 +687,7 @@ "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", "LabelInNetworkSignInWithEasyPasswordHelp": "Use the easy pin code to sign in to clients within your local network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "LabelInternetQuality": "Internet quality:", + "LabelIsForced": "Forced", "LabelKeepUpTo": "Keep up to:", "LabelKidsCategories": "Children's categories:", "LabelKodiMetadataDateFormat": "Release date format:", diff --git a/src/strings/fr.json b/src/strings/fr.json index 3f1d22c75a..625a15f3b3 100644 --- a/src/strings/fr.json +++ b/src/strings/fr.json @@ -271,6 +271,7 @@ "HeaderAddToCollection": "Ajouter à la collection", "HeaderAddToPlaylist": "Ajouter à la liste de lecture", "HeaderAddUpdateImage": "Ajouter/Mettre à jour une image", + "HeaderAddUpdateSubtitle": "Ajouter/Mettre à jour des sous-titres", "HeaderAddUser": "Ajouter un utilisateur", "HeaderAdditionalParts": "Parties additionelles", "HeaderAdmin": "Administrateur", @@ -457,6 +458,7 @@ "HeaderTypeText": "Entrer texte", "HeaderUpcomingOnTV": "Prochainement à la TV", "HeaderUploadImage": "Envoyer une image", + "HeaderUploadSubtitle": "Envoyer des sous-titres", "HeaderUser": "Utilisateur", "HeaderUsers": "Utilisateurs", "HeaderVideoQuality": "Qualité vidéo", @@ -564,6 +566,7 @@ "LabelDownloadLanguages": "Téléchargement des langues :", "LabelDropImageHere": "Faites glisser l'image ici, ou cliquez pour parcourir vos fichiers.", "LabelDropShadow": "Ombre portée :", + "LabelDropSubtitleHere": "Faites glisser les sous-tires ici, ou cliquez pour parcourir vos fichiers.", "LabelDynamicExternalId": "ID {0} :", "LabelEasyPinCode": "Code Easy PIN :", "LabelEmbedAlbumArtDidl": "Intégrer les images d'album dans le DIDL", @@ -620,6 +623,7 @@ "LabelInNetworkSignInWithEasyPassword": "Activer l'authentification simplifiée dans les réseaux domestiques avec mon code Easy PIN", "LabelInNetworkSignInWithEasyPasswordHelp": "Utilisez votre code Easy PIN pour vous connecter aux applications depuis l'intérieur de votre réseau local. Votre mot de passe habituel ne sera requis que depuis l'extérieur. Si le code PIN n'est pas défini, vous n'aurez pas besoin de mot de passe depuis l'intérieur de votre réseau local.", "LabelInternetQuality": "Qualité d'internet :", + "LabelIsForced": "Forcés", "LabelKeepUpTo": "Garder jusqu'à :", "LabelKidsCategories": "Catégories jeunesse :", "LabelKodiMetadataDateFormat": "Format de la date de sortie :", From c5cb1028aee54ba89f7b79f2046b26747c02ab25 Mon Sep 17 00:00:00 2001 From: matjaz321 Date: Thu, 13 Aug 2020 22:35:04 +0200 Subject: [PATCH 006/202] Added onError eventListener to the youtube iframe video player to destroy itself whenever it receives any errors --- src/plugins/youtubePlayer/plugin.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plugins/youtubePlayer/plugin.js b/src/plugins/youtubePlayer/plugin.js index eed75a8116..c83fac1b82 100644 --- a/src/plugins/youtubePlayer/plugin.js +++ b/src/plugins/youtubePlayer/plugin.js @@ -142,7 +142,11 @@ function setCurrentSrc(instance, elem, options) { } else if (event.data === YT.PlayerState.PAUSED) { events.trigger(instance, 'pause'); } - } + }, + 'onError': () => { + instance.destroy(); + loading.hide(); + }, }, playerVars: { controls: 0, From a50e4853e3206934c1fcaa9a950beb476e3a416f Mon Sep 17 00:00:00 2001 From: matjaz321 Date: Thu, 13 Aug 2020 22:40:01 +0200 Subject: [PATCH 007/202] linting fixes --- src/plugins/youtubePlayer/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/youtubePlayer/plugin.js b/src/plugins/youtubePlayer/plugin.js index c83fac1b82..7225de5960 100644 --- a/src/plugins/youtubePlayer/plugin.js +++ b/src/plugins/youtubePlayer/plugin.js @@ -146,7 +146,7 @@ function setCurrentSrc(instance, elem, options) { 'onError': () => { instance.destroy(); loading.hide(); - }, + } }, playerVars: { controls: 0, From 865e9085ef8fdc32d6ebcee8aaa68fb2b0a79f2f Mon Sep 17 00:00:00 2001 From: matjaz321 Date: Wed, 19 Aug 2020 21:32:22 +0200 Subject: [PATCH 008/202] CR fixes --- src/components/playback/playbackmanager.js | 4 ++++ src/plugins/youtubePlayer/plugin.js | 5 +---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 3b4099d540..9959544ae7 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -2260,6 +2260,10 @@ class PlaybackManager { }, function () { // TODO: show error message self.stop(player); + loading.hide(); + }).catch(() => { + player.destroy(); + loading.hide(); }); }); } diff --git a/src/plugins/youtubePlayer/plugin.js b/src/plugins/youtubePlayer/plugin.js index 7225de5960..2ac9a63783 100644 --- a/src/plugins/youtubePlayer/plugin.js +++ b/src/plugins/youtubePlayer/plugin.js @@ -143,10 +143,7 @@ function setCurrentSrc(instance, elem, options) { events.trigger(instance, 'pause'); } }, - 'onError': () => { - instance.destroy(); - loading.hide(); - } + 'onError': () => reject(), }, playerVars: { controls: 0, From 73e6f3c03fa7bdb84d90743e645cafa351315a41 Mon Sep 17 00:00:00 2001 From: matjaz321 Date: Wed, 19 Aug 2020 21:35:51 +0200 Subject: [PATCH 009/202] fixed linting error --- src/plugins/youtubePlayer/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/youtubePlayer/plugin.js b/src/plugins/youtubePlayer/plugin.js index 2ac9a63783..9079e2bcb6 100644 --- a/src/plugins/youtubePlayer/plugin.js +++ b/src/plugins/youtubePlayer/plugin.js @@ -143,7 +143,7 @@ function setCurrentSrc(instance, elem, options) { events.trigger(instance, 'pause'); } }, - 'onError': () => reject(), + 'onError': () => reject() }, playerVars: { controls: 0, From d6441934416cdd916ee5bb187f3c14eda686b7dc Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Thu, 3 Sep 2020 01:04:21 +0300 Subject: [PATCH 010/202] Return permanent scrollbar (killed by refactoring) --- src/assets/css/site.css | 9 +++++---- src/components/slideshow/slideshow.js | 2 -- src/plugins/htmlVideoPlayer/plugin.js | 3 ++- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/assets/css/site.css b/src/assets/css/site.css index 38e056df89..9eb61de074 100644 --- a/src/assets/css/site.css +++ b/src/assets/css/site.css @@ -44,6 +44,11 @@ body { overflow-x: hidden; background-color: transparent !important; -webkit-font-smoothing: antialiased; + + /* This keeps the scrollbar always present in all pages, so we avoid clipping while switching between pages + that need the scrollbar and pages that don't. + */ + overflow-y: scroll; } .mainAnimatedPage { @@ -122,10 +127,6 @@ div[data-role=page] { padding-bottom: 4em; } -.force-scroll { - overflow-y: scroll; -} - .hide-scroll { overflow-y: hidden; } diff --git a/src/components/slideshow/slideshow.js b/src/components/slideshow/slideshow.js index 028c21b221..f41f864848 100644 --- a/src/components/slideshow/slideshow.js +++ b/src/components/slideshow/slideshow.js @@ -492,7 +492,6 @@ export default function (options) { document.removeEventListener((window.PointerEvent ? 'pointermove' : 'mousemove'), onPointerMove); // Shows page scrollbar document.body.classList.remove('hide-scroll'); - document.body.classList.add('force-scroll'); } /** @@ -657,7 +656,6 @@ export default function (options) { self.show = function () { createElements(options); // Hides page scrollbar - document.body.classList.remove('force-scroll'); document.body.classList.add('hide-scroll'); }; diff --git a/src/plugins/htmlVideoPlayer/plugin.js b/src/plugins/htmlVideoPlayer/plugin.js index d07e6aae58..9b9b7011da 100644 --- a/src/plugins/htmlVideoPlayer/plugin.js +++ b/src/plugins/htmlVideoPlayer/plugin.js @@ -107,7 +107,7 @@ function tryRemoveElement(elem) { const animatedPage = document.querySelector('.page:not(.hide)'); animatedPage.classList.add('hide'); // At this point, we must hide the scrollbar placeholder, so it's not being displayed while the item is being loaded - document.body.classList.remove('force-scroll'); + document.body.classList.add('hide-scroll'); } function zoomIn(elem) { @@ -679,6 +679,7 @@ function tryRemoveElement(elem) { destroyFlvPlayer(this); appRouter.setTransparency('none'); + document.body.classList.remove('hide-scroll'); const videoElement = this.#mediaElement; From 74227f38f53649b8532e2f2e3503f13ad0e7f536 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Thu, 3 Sep 2020 01:40:36 +0300 Subject: [PATCH 011/202] Fix scrollbar for Youtube player --- src/plugins/youtubePlayer/plugin.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/youtubePlayer/plugin.js b/src/plugins/youtubePlayer/plugin.js index eed75a8116..57e49e1d1a 100644 --- a/src/plugins/youtubePlayer/plugin.js +++ b/src/plugins/youtubePlayer/plugin.js @@ -37,6 +37,9 @@ function createMediaElement(instance, options) { document.body.insertBefore(dlg, document.body.firstChild); instance.videoDialog = dlg; + // At this point, we must hide the scrollbar placeholder, so it's not being displayed while the item is being loaded + document.body.classList.add('hide-scroll'); + if (options.fullscreen && dlg.animate && !browser.slow) { zoomIn(dlg, 1).onfinish = function () { resolve(videoElement); @@ -214,6 +217,7 @@ class YoutubePlayer { } destroy() { appRouter.setTransparency('none'); + document.body.classList.remove('hide-scroll'); const dlg = this.videoDialog; if (dlg) { From cb1d2887fa1d5d8fffafbbebb4636d58d97b6bf0 Mon Sep 17 00:00:00 2001 From: dkanada Date: Thu, 10 Sep 2020 23:20:55 +0900 Subject: [PATCH 012/202] fix startup wizard redirect and standalone mode --- gulpfile.js | 32 ++------------ src/components/appRouter.js | 46 ++++++++++---------- src/components/require/requiretext.js | 2 +- src/controllers/dashboard/general.js | 4 -- src/scripts/clientUtils.js | 61 +++++++++++++-------------- src/scripts/settings/userSettings.js | 2 +- src/scripts/site.js | 44 +++++++++---------- src/standalone.js | 4 -- 8 files changed, 78 insertions(+), 117 deletions(-) delete mode 100644 src/standalone.js diff --git a/gulpfile.js b/gulpfile.js index 8b407ec2aa..7d1184dbdd 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -2,7 +2,6 @@ const { src, dest, series, parallel, watch } = require('gulp'); const browserSync = require('browser-sync').create(); const del = require('del'); const babel = require('gulp-babel'); -const concat = require('gulp-concat'); const terser = require('gulp-terser'); const htmlmin = require('gulp-htmlmin'); const imagemin = require('gulp-imagemin'); @@ -16,7 +15,6 @@ const stream = require('webpack-stream'); const inject = require('gulp-inject'); const postcss = require('gulp-postcss'); const sass = require('gulp-sass'); -const gulpif = require('gulp-if'); const lazypipe = require('lazypipe'); sass.compiler = require('node-sass'); @@ -30,10 +28,7 @@ if (mode.production()) { const options = { javascript: { - query: ['src/**/*.js', '!src/bundle.js', '!src/standalone.js', '!src/scripts/apploader.js'] - }, - apploader: { - query: ['src/standalone.js', 'src/scripts/apploader.js'] + query: ['src/**/*.js', '!src/bundle.js'] }, css: { query: ['src/**/*.css', 'src/**/*.scss'] @@ -68,8 +63,6 @@ function serve() { } }); - watch(options.apploader.query, apploader(true)); - watch('src/bundle.js', webpack); watch(options.css.query).on('all', function (event, path) { @@ -131,20 +124,6 @@ function javascript(query) { .pipe(browserSync.stream()); } -function apploader(standalone) { - function task() { - return src(options.apploader.query, { base: './src/' }) - .pipe(gulpif(standalone, concat('scripts/apploader.js'))) - .pipe(pipelineJavascript()) - .pipe(dest('dist/')) - .pipe(browserSync.stream()); - } - - task.displayName = 'apploader'; - - return task; -} - function webpack() { return stream(config) .pipe(dest('dist/')) @@ -195,10 +174,5 @@ function injectBundle() { .pipe(browserSync.stream()); } -function build(standalone) { - return series(clean, parallel(javascript, apploader(standalone), webpack, css, html, images, copy)); -} - -exports.default = series(build(false), injectBundle); -exports.standalone = series(build(true), injectBundle); -exports.serve = series(exports.standalone, serve); +exports.default = series(clean, parallel(javascript, webpack, css, html, images, copy), injectBundle); +exports.serve = series(exports.default, serve); diff --git a/src/components/appRouter.js b/src/components/appRouter.js index a6bb6da618..e1c0467d3f 100644 --- a/src/components/appRouter.js +++ b/src/components/appRouter.js @@ -8,6 +8,7 @@ import itemHelper from 'itemHelper'; import loading from 'loading'; import page from 'page'; import viewManager from 'viewManager'; +import * as webSettings from 'webSettings'; class AppRouter { allRoutes = []; @@ -72,15 +73,11 @@ class AppRouter { } showVideoOsd() { - return Dashboard.navigate('video'); + Dashboard.navigate('video'); } showSelectServer() { - Dashboard.navigate(AppInfo.isNativeApp ? 'selectserver.html' : 'login.html'); - } - - showWelcome() { - Dashboard.navigate(AppInfo.isNativeApp ? 'selectserver.html' : 'login.html'); + Dashboard.navigate('selectserver.html'); } showSettings() { @@ -282,9 +279,6 @@ class AppRouter { case 'ServerSelection': this.showSelectServer(); break; - case 'ConnectSignIn': - this.showWelcome(); - break; case 'ServerUpdateNeeded': import('alert').then(({default: alert}) =>{ alert({ @@ -510,25 +504,33 @@ class AppRouter { authenticate(ctx, route, callback) { const firstResult = this.firstConnectionResult; - if (firstResult) { - this.firstConnectionResult = null; - if (firstResult.State !== 'SignedIn' && !route.anonymous) { - this.handleConnectionResult(firstResult); - return; - } + this.firstConnectionResult = null; + if (firstResult && firstResult.State === 'ServerSignIn' && !route.anonymous) { + let url = ApiClient.serverAddress() + '/System/Info/Public'; + fetch(url).then(response => { + if (!response.ok) return; + response.json().then(data => { + if (data !== null && data.StartupWizardCompleted === false) { + Dashboard.navigate('wizardstart.html'); + } else { + this.handleConnectionResult(firstResult); + } + }); + }).catch(error => { + console.error(error); + }); } + console.debug('processing path request: ' + pathname); const apiClient = window.connectionManager.currentApiClient(); const pathname = ctx.pathname.toLowerCase(); - console.debug('appRouter - processing path request ' + pathname); - const isCurrentRouteStartup = this.currentRouteInfo ? this.currentRouteInfo.route.startup : true; const shouldExitApp = ctx.isBack && route.isDefaultRoute && isCurrentRouteStartup; if (!shouldExitApp && (!apiClient || !apiClient.isLoggedIn()) && !route.anonymous) { - console.debug('appRouter - route does not allow anonymous access, redirecting to login'); + console.debug('route does not allow anonymous access: redirecting to login'); this.beginConnectionWizard(); return; } @@ -536,16 +538,16 @@ class AppRouter { if (shouldExitApp) { if (appHost.supports('exit')) { appHost.exit(); - return; } + return; } if (apiClient && apiClient.isLoggedIn()) { - console.debug('appRouter - user is authenticated'); + console.debug('user is authenticated'); if (route.isDefaultRoute) { - console.debug('appRouter - loading skin home page'); + console.debug('loading home page'); Emby.Page.goHome(); return; } else if (route.roles) { @@ -556,7 +558,7 @@ class AppRouter { } } - console.debug('appRouter - proceeding to ' + pathname); + console.debug('proceeding to page: ' + pathname); callback(); } diff --git a/src/components/require/requiretext.js b/src/components/require/requiretext.js index 28ddeb21c8..ae1edbfc2d 100644 --- a/src/components/require/requiretext.js +++ b/src/components/require/requiretext.js @@ -2,7 +2,7 @@ define(function () { 'use strict'; // hack to work around the server's auto-redirection feature - var addRedirectPrevention = window.dashboardVersion != null && window.Dashboard && !window.AppInfo.isNativeApp; + var addRedirectPrevention = window.dashboardVersion != null && window.Dashboard; return { diff --git a/src/controllers/dashboard/general.js b/src/controllers/dashboard/general.js index eb819dc415..78fc8f8388 100644 --- a/src/controllers/dashboard/general.js +++ b/src/controllers/dashboard/general.js @@ -44,10 +44,6 @@ import 'emby-button'; ApiClient.updateNamedConfiguration(brandingConfigKey, brandingConfig).then(function () { Dashboard.processServerConfigurationUpdateResult(); - - if (requiresReload && !AppInfo.isNativeApp) { - window.location.reload(true); - } }); }); }, function () { diff --git a/src/scripts/clientUtils.js b/src/scripts/clientUtils.js index 4d3c049e8c..097abc4c91 100644 --- a/src/scripts/clientUtils.js +++ b/src/scripts/clientUtils.js @@ -1,35 +1,41 @@ +import * as webSettings from 'webSettings'; export function getCurrentUser() { return window.ApiClient.getCurrentUser(false); } -//TODO: investigate url prefix support for serverAddress function -export function serverAddress() { - if (AppInfo.isNativeApp) { - const apiClient = window.ApiClient; +// TODO: investigate url prefix support for serverAddress function +export async function serverAddress() { + const apiClient = window.ApiClient; - if (apiClient) { - return apiClient.serverAddress(); + if (apiClient) { + return Promise.resolve(apiClient.serverAddress()); + } + + let current = await window.connectionManager.getAvailableServers().then(servers => { + if (servers.length !== 0) { + return Promise.resolve(servers[0].ManualAddress); } + }); - return null; - } + if (current) return Promise.resolve(current); - const urlLower = window.location.href.toLowerCase(); - const index = urlLower.lastIndexOf('/web'); + let urls = []; + urls.push(`${window.location.origin}/System/Info/Public`); + urls.push(`${window.location.protocol}//${window.location.hostname}:8096/System/Info/Public`); - if (index != -1) { - return urlLower.substring(0, index); - } + let promises = urls.map(url => { + return fetch(url).catch(error => { + return Promise.resolve(); + }); + }); - const loc = window.location; - let address = loc.protocol + '//' + loc.hostname; - - if (loc.port) { - address += ':' + loc.port; - } - - return address; + return Promise.all(promises).then(responses => { + return responses.find(response => response && response.ok); + }).then(response => response.url).catch(error => { + console.log(error); + return Promise.resolve(); + }); } export function getCurrentUserId() { @@ -49,16 +55,9 @@ export function onServerChanged(userId, accessToken, apiClient) { export function logout() { window.connectionManager.logout().then(function () { - let loginPage; - - if (AppInfo.isNativeApp) { - loginPage = 'selectserver.html'; - window.ApiClient = null; - } else { - loginPage = 'login.html'; - } - - navigate(loginPage); + webSettings.getMultiServer().then(multi => { + multi ? navigate('selectserver.html') : navigate('login.html'); + }); }); } diff --git a/src/scripts/settings/userSettings.js b/src/scripts/settings/userSettings.js index 1235e0fa5f..263d74ed37 100644 --- a/src/scripts/settings/userSettings.js +++ b/src/scripts/settings/userSettings.js @@ -209,7 +209,7 @@ export class UserSettings { } val = this.get('enableBackdrops', false); - return val !== 'false'; + return val === 'true'; } /** diff --git a/src/scripts/site.js b/src/scripts/site.js index f14670d82d..adb0d65215 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -63,7 +63,7 @@ function initClient() { if (!localApiClient) { var server = window.connectionManager.getLastUsedServer(); - if (server) { + if (server && server.Id) { localApiClient = window.connectionManager.getApiClient(server.Id); } } @@ -83,40 +83,38 @@ function initClient() { } function createConnectionManager() { - return require(['connectionManagerFactory', 'apphost', 'credentialprovider', 'events', 'userSettings'], function (ConnectionManager, appHost, credentialProvider, events, userSettings) { + return require(['connectionManagerFactory', 'apphost', 'credentialprovider', 'events', 'userSettings', 'apiclient', 'clientUtils'], function (ConnectionManager, appHost, credentialProvider, events, userSettings, apiClientFactory, clientUtils) { appHost = appHost.default || appHost; var credentialProviderInstance = new credentialProvider(); var promises = [appHost.init()]; - return Promise.all(promises).then(function (responses) { + return Promise.all(promises).then(responses => { var capabilities = Dashboard.capabilities(appHost); window.connectionManager = new ConnectionManager(credentialProviderInstance, appHost.appName(), appHost.appVersion(), appHost.deviceName(), appHost.deviceId(), capabilities); bindConnectionManagerEvents(window.connectionManager, events, userSettings); + clientUtils.serverAddress().then(server => { + if (!server) { + Dashboard.navigate('selectserver.html'); + return; + } - if (!AppInfo.isNativeApp) { - console.debug('loading ApiClient singleton'); + console.debug('creating apiclient singleton'); + let parts = server.split('/'); + let url = parts[0] + '//' + parts[2]; + var apiClient = new apiClientFactory(url, appHost.appName(), appHost.appVersion(), appHost.deviceName(), appHost.deviceId()); - return require(['apiclient', 'clientUtils'], function (apiClientFactory, clientUtils) { - console.debug('creating ApiClient singleton'); + apiClient.enableAutomaticNetworking = false; + apiClient.manualAddressOnly = true; - var apiClient = new apiClientFactory(Dashboard.serverAddress(), appHost.appName(), appHost.appVersion(), appHost.deviceName(), appHost.deviceId()); + window.connectionManager.addApiClient(apiClient); + window.ApiClient = apiClient; + console.debug('loaded apiclient singleton'); - apiClient.enableAutomaticNetworking = false; - apiClient.manualAddressOnly = true; - - window.connectionManager.addApiClient(apiClient); - - window.ApiClient = apiClient; - localApiClient = apiClient; - - console.debug('loaded ApiClient singleton'); - }); - } - - return Promise.resolve(); + return Promise.resolve(); + }); }); }); } @@ -434,10 +432,6 @@ function initClient() { define('castSenderApiLoader', [componentsPath + '/castSenderApi'], returnFirstDependency); - if (window.appMode === 'cordova' || window.appMode === 'android' || window.appMode === 'standalone') { - AppInfo.isNativeApp = true; - } - init(); } diff --git a/src/standalone.js b/src/standalone.js deleted file mode 100644 index 237872703a..0000000000 --- a/src/standalone.js +++ /dev/null @@ -1,4 +0,0 @@ -(function() { - 'use strict'; - window.appMode = 'standalone'; -})(); From 5d8fdc311fd43a2ab7576c7ba63c207311f678e5 Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 12 Sep 2020 08:34:08 +0900 Subject: [PATCH 013/202] remove standalone build from azure --- .ci/azure-pipelines-build.yml | 6 ------ README.md | 10 ++-------- package.json | 1 - 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/.ci/azure-pipelines-build.yml b/.ci/azure-pipelines-build.yml index 128fe54605..026afe76a6 100644 --- a/.ci/azure-pipelines-build.yml +++ b/.ci/azure-pipelines-build.yml @@ -8,8 +8,6 @@ jobs: BuildConfiguration: development Production: BuildConfiguration: production - Standalone: - BuildConfiguration: standalone pool: vmImage: 'ubuntu-latest' @@ -39,10 +37,6 @@ jobs: displayName: 'Build Production' condition: eq(variables['BuildConfiguration'], 'production') - - script: 'yarn build:standalone' - displayName: 'Build Standalone' - condition: eq(variables['BuildConfiguration'], 'standalone') - - script: 'test -d dist' displayName: 'Check Build' diff --git a/README.md b/README.md index ca42965dd9..1108ec9f21 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Jellyfin Web is the frontend used for most of the clients available for end user ### Dependencies -- [Node.js](https://nodejs.org/en/download/) +- [Node.js](https://nodejs.org/en/download) - [Yarn 1.22.4](https://classic.yarnpkg.com/en/docs/install) - Gulp-cli @@ -69,14 +69,8 @@ Jellyfin Web is the frontend used for most of the clients available for end user yarn serve ``` -4. Build the client with sourcemaps. +4. Build the client with sourcemaps available. ```sh yarn build:development ``` - - You can build a nginx compatible version as well. - - ```sh - yarn build:standalone - ``` diff --git a/package.json b/package.json index 3a74cd9d67..df433ed9b8 100644 --- a/package.json +++ b/package.json @@ -392,7 +392,6 @@ "prepare": "gulp --production", "build:development": "gulp --development", "build:production": "gulp --production", - "build:standalone": "gulp standalone --development", "lint": "eslint \".\"", "stylelint": "stylelint \"src/**/*.css\"" } From 4553215841936e2c2c089e4869004771007b0c9e Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 12 Sep 2020 08:41:04 +0900 Subject: [PATCH 014/202] add code suggestions --- src/components/appRouter.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/appRouter.js b/src/components/appRouter.js index e1c0467d3f..1d25543c35 100644 --- a/src/components/appRouter.js +++ b/src/components/appRouter.js @@ -509,23 +509,23 @@ class AppRouter { if (firstResult && firstResult.State === 'ServerSignIn' && !route.anonymous) { let url = ApiClient.serverAddress() + '/System/Info/Public'; fetch(url).then(response => { - if (!response.ok) return; - response.json().then(data => { - if (data !== null && data.StartupWizardCompleted === false) { - Dashboard.navigate('wizardstart.html'); - } else { - this.handleConnectionResult(firstResult); - } - }); + if (!response.ok) return Promise.reject('fetch failed'); + return response.json(); + }).then(data => { + if (data !== null && data.StartupWizardCompleted === false) { + Dashboard.navigate('wizardstart.html'); + } else { + this.handleConnectionResult(firstResult); + } }).catch(error => { console.error(error); }); } - console.debug('processing path request: ' + pathname); const apiClient = window.connectionManager.currentApiClient(); const pathname = ctx.pathname.toLowerCase(); + console.debug('processing path request: ' + pathname); const isCurrentRouteStartup = this.currentRouteInfo ? this.currentRouteInfo.route.startup : true; const shouldExitApp = ctx.isBack && route.isDefaultRoute && isCurrentRouteStartup; From 982ae411c59cb95421ea870b0dd1726662fe15d5 Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 12 Sep 2020 09:12:40 +0900 Subject: [PATCH 015/202] fix linting issues and add servers to web config --- src/components/appRouter.js | 2 +- src/config.template.json | 1 + src/scripts/clientUtils.js | 15 ++++++++------- src/scripts/settings/webSettings.js | 9 +++++++++ src/scripts/site.js | 10 ++++------ 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/components/appRouter.js b/src/components/appRouter.js index 1d25543c35..0c3c1d4533 100644 --- a/src/components/appRouter.js +++ b/src/components/appRouter.js @@ -507,7 +507,7 @@ class AppRouter { this.firstConnectionResult = null; if (firstResult && firstResult.State === 'ServerSignIn' && !route.anonymous) { - let url = ApiClient.serverAddress() + '/System/Info/Public'; + const url = ApiClient.serverAddress() + '/System/Info/Public'; fetch(url).then(response => { if (!response.ok) return Promise.reject('fetch failed'); return response.json(); diff --git a/src/config.template.json b/src/config.template.json index 0f308ccc11..2ea8f89457 100644 --- a/src/config.template.json +++ b/src/config.template.json @@ -1,5 +1,6 @@ { "multiserver": false, + "servers": [], "themes": [ { "name": "Apple TV", diff --git a/src/scripts/clientUtils.js b/src/scripts/clientUtils.js index 097abc4c91..d165666734 100644 --- a/src/scripts/clientUtils.js +++ b/src/scripts/clientUtils.js @@ -12,7 +12,7 @@ export async function serverAddress() { return Promise.resolve(apiClient.serverAddress()); } - let current = await window.connectionManager.getAvailableServers().then(servers => { + const current = await window.connectionManager.getAvailableServers().then(servers => { if (servers.length !== 0) { return Promise.resolve(servers[0].ManualAddress); } @@ -20,19 +20,20 @@ export async function serverAddress() { if (current) return Promise.resolve(current); - let urls = []; - urls.push(`${window.location.origin}/System/Info/Public`); - urls.push(`${window.location.protocol}//${window.location.hostname}:8096/System/Info/Public`); + const urls = []; + urls.push(window.location.origin); + urls.push(`${window.location.protocol}//${window.location.hostname}:8096`); + urls.push(await webSettings.getServers()); - let promises = urls.map(url => { - return fetch(url).catch(error => { + const promises = urls.map(url => { + return fetch(`${url}/System/Info/Public`).catch(error => { return Promise.resolve(); }); }); return Promise.all(promises).then(responses => { return responses.find(response => response && response.ok); - }).then(response => response.url).catch(error => { + }).then(response => response.url.replace('/System/Info/Public', '')).catch(error => { console.log(error); return Promise.resolve(); }); diff --git a/src/scripts/settings/webSettings.js b/src/scripts/settings/webSettings.js index 2ffe290d88..be28ae730f 100644 --- a/src/scripts/settings/webSettings.js +++ b/src/scripts/settings/webSettings.js @@ -46,6 +46,15 @@ export function getMultiServer() { }); } +export function getServers() { + return getConfig().then(config => { + return config.servers; + }).catch(error => { + console.log('cannot get web config:', error); + return []; + }); +} + export function getThemes() { return getConfig().then(config => { return config.themes; diff --git a/src/scripts/site.js b/src/scripts/site.js index adb0d65215..0123eceed2 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -86,11 +86,11 @@ function initClient() { return require(['connectionManagerFactory', 'apphost', 'credentialprovider', 'events', 'userSettings', 'apiclient', 'clientUtils'], function (ConnectionManager, appHost, credentialProvider, events, userSettings, apiClientFactory, clientUtils) { appHost = appHost.default || appHost; - var credentialProviderInstance = new credentialProvider(); - var promises = [appHost.init()]; + const credentialProviderInstance = new credentialProvider(); + const promises = [appHost.init()]; return Promise.all(promises).then(responses => { - var capabilities = Dashboard.capabilities(appHost); + const capabilities = Dashboard.capabilities(appHost); window.connectionManager = new ConnectionManager(credentialProviderInstance, appHost.appName(), appHost.appVersion(), appHost.deviceName(), appHost.deviceId(), capabilities); @@ -102,9 +102,7 @@ function initClient() { } console.debug('creating apiclient singleton'); - let parts = server.split('/'); - let url = parts[0] + '//' + parts[2]; - var apiClient = new apiClientFactory(url, appHost.appName(), appHost.appVersion(), appHost.deviceName(), appHost.deviceId()); + const apiClient = new apiClientFactory(server, appHost.appName(), appHost.appVersion(), appHost.deviceName(), appHost.deviceId()); apiClient.enableAutomaticNetworking = false; apiClient.manualAddressOnly = true; From b973a5eace34f81a1ccb59239c95fa1545cbfb17 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Sat, 26 Sep 2020 21:16:34 +0300 Subject: [PATCH 016/202] Make all fullscreen dialogs hide scrollbar --- src/components/dialogHelper/dialogHelper.js | 8 ++++---- src/components/slideshow/slideshow.js | 4 ---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/components/dialogHelper/dialogHelper.js b/src/components/dialogHelper/dialogHelper.js index eb46d98b12..65f2a07a19 100644 --- a/src/components/dialogHelper/dialogHelper.js +++ b/src/components/dialogHelper/dialogHelper.js @@ -310,10 +310,6 @@ import 'scrollStyles'; const 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; } @@ -322,6 +318,10 @@ import 'scrollStyles'; return true; } + if (supportsOverscrollBehavior && (options.size || !browser.touch)) { + return false; + } + if (options.size) { return true; } diff --git a/src/components/slideshow/slideshow.js b/src/components/slideshow/slideshow.js index f41f864848..e825bd0b8a 100644 --- a/src/components/slideshow/slideshow.js +++ b/src/components/slideshow/slideshow.js @@ -490,8 +490,6 @@ export default function (options) { inputManager.off(window, onInputCommand); /* eslint-disable-next-line compat/compat */ document.removeEventListener((window.PointerEvent ? 'pointermove' : 'mousemove'), onPointerMove); - // Shows page scrollbar - document.body.classList.remove('hide-scroll'); } /** @@ -655,8 +653,6 @@ export default function (options) { */ self.show = function () { createElements(options); - // Hides page scrollbar - document.body.classList.add('hide-scroll'); }; /** From 78a3c971ff0e508b1fc367d25bcf3915c0bf319d Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Sat, 26 Sep 2020 21:48:22 +0300 Subject: [PATCH 017/202] Fix unstyled scrollbar --- src/assets/css/site.css | 9 ++++----- src/scripts/autoThemes.js | 6 +++++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/assets/css/site.css b/src/assets/css/site.css index 9eb61de074..38e056df89 100644 --- a/src/assets/css/site.css +++ b/src/assets/css/site.css @@ -44,11 +44,6 @@ body { overflow-x: hidden; background-color: transparent !important; -webkit-font-smoothing: antialiased; - - /* This keeps the scrollbar always present in all pages, so we avoid clipping while switching between pages - that need the scrollbar and pages that don't. - */ - overflow-y: scroll; } .mainAnimatedPage { @@ -127,6 +122,10 @@ div[data-role=page] { padding-bottom: 4em; } +.force-scroll { + overflow-y: scroll; +} + .hide-scroll { overflow-y: hidden; } diff --git a/src/scripts/autoThemes.js b/src/scripts/autoThemes.js index e278a80dc9..daf8ae581b 100644 --- a/src/scripts/autoThemes.js +++ b/src/scripts/autoThemes.js @@ -3,7 +3,11 @@ import skinManager from 'skinManager'; import events from 'events'; // Set the default theme when loading -skinManager.setTheme(userSettings.theme()); +skinManager.setTheme(userSettings.theme()) + /* This keeps the scrollbar always present in all pages, so we avoid clipping while switching between pages + that need the scrollbar and pages that don't. + */ + .then(() => document.body.classList.add('force-scroll')); // Set the user's prefered theme when signing in events.on(window.connectionManager, 'localusersignedin', function (e, user) { From da50605b4e9eed88be771a38d5b6a0362fca8cd8 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Sat, 26 Sep 2020 23:55:02 +0300 Subject: [PATCH 018/202] Hide scrollbar only for fullscreen --- src/plugins/youtubePlayer/plugin.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/plugins/youtubePlayer/plugin.js b/src/plugins/youtubePlayer/plugin.js index 57e49e1d1a..5b921010a2 100644 --- a/src/plugins/youtubePlayer/plugin.js +++ b/src/plugins/youtubePlayer/plugin.js @@ -15,6 +15,10 @@ function zoomIn(elem, iterations) { return elem.animate(keyframes, timing); } +function hideScroll() { + document.body.classList.add('hide-scroll'); +} + function createMediaElement(instance, options) { return new Promise(function (resolve, reject) { const dlg = document.querySelector('.youtubePlayerContainer'); @@ -37,8 +41,9 @@ function createMediaElement(instance, options) { document.body.insertBefore(dlg, document.body.firstChild); instance.videoDialog = dlg; - // At this point, we must hide the scrollbar placeholder, so it's not being displayed while the item is being loaded - document.body.classList.add('hide-scroll'); + if (options.fullscreen) { + hideScroll(); + } if (options.fullscreen && dlg.animate && !browser.slow) { zoomIn(dlg, 1).onfinish = function () { @@ -49,6 +54,10 @@ function createMediaElement(instance, options) { } }); } else { + if (options.fullscreen) { + hideScroll(); + } + resolve(dlg.querySelector('#player')); } }); From db4235e2f893a79fb703d9d23c09f616ac1ee473 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sat, 10 Oct 2020 13:20:41 +0100 Subject: [PATCH 019/202] Add files via upload For use with https://github.com/jellyfin/jellyfin/pull/4124 --- src/controllers/dashboard/networking.html | 202 ++++++++++++++++++++++ src/controllers/dashboard/networking.js | 88 +++++++--- 2 files changed, 268 insertions(+), 22 deletions(-) create mode 100644 src/controllers/dashboard/networking.html diff --git a/src/controllers/dashboard/networking.html b/src/controllers/dashboard/networking.html new file mode 100644 index 0000000000..0102cd5ab8 --- /dev/null +++ b/src/controllers/dashboard/networking.html @@ -0,0 +1,202 @@ +
+
+
+
+
+ + +
+

${HeaderServerAddressSettings}

+ +
+ +
${LabelLocalHttpServerPortNumberHelp}
+
+ +
+ +
${LabelEnableHttpsHelp}
+
+ +
+ +
${LabelHttpsPortHelp}
+
+ +
+ +
${LabelBaseUrlHelp}
+
+ +
+ +
${LabelBindToLocalNetworkAddressHelp}
+
+ +
+ +
${LanNetworksHelp}
+
+ +
+ +
${KnownProxiesHelp}
+
+
+ +
+

${HeaderHttpsSettings}

+ +
+ +
${LabelRequireHttpsHelp}
+
+ +
+
+
+ +
+ +
+
${LabelCustomCertificatePathHelp}
+
+ +
+ +
${LabelCertificatePasswordHelp}
+
+
+ +
+

${HeaderRemoteAccessSettings}

+ +
+ +
${AllowRemoteAccessHelp}
+
+
+ +
${AllowedRemoteAddressesHelp}
+
+
+ +
+ +
+ +
${LabelEnableAutomaticPortMapHelp}
+
+
+ +
${LabelCreateHttpPortMapHelp}
+
+
+ +
${LabelPublicHttpPortHelp}
+
+
+ +
${LabelPublicHttpsPortHelp}
+
+
+ +
+

${HeaderNetworking}

+
+ +
${LabelEnableIP4Help}
+
+
+ +
${LabelEnableIP6Help}
+
+
+ + +
+

${HeaderAutoDiscovery}

+
+ +
${LabelAutomaticDiscoveryHelp}
+
+
+ +
+

${HeaderPortRanges}

+ +
+ +
${LabelPublishedServerUriHelp}
+
+
+ +
${LabelUDPPortRangeHelp}
+
+
+ +
${LabelHDHomerunPortRangeHelp}
+
+
+ +
+

${HeaderDebugging}

+
+ +
${LabelEnableSSDPTracingHelp}
+
+
+ +
${LabelSSDPTracingFilterHelp}
+
+
+ +
${LabelAutoDiscoveryTracingHelp}
+
+
+
+
+ +
+
+
+
+
diff --git a/src/controllers/dashboard/networking.js b/src/controllers/dashboard/networking.js index 4ddde7f24c..8d9b9fa531 100644 --- a/src/controllers/dashboard/networking.js +++ b/src/controllers/dashboard/networking.js @@ -1,12 +1,16 @@ -define(['loading', 'libraryMenu', 'globalize', 'emby-checkbox', 'emby-select'], function (loading, libraryMenu, globalize) { - 'use strict'; +import loading from 'loading'; +import globalize from 'globalize'; +import 'emby-checkbox'; +import 'emby-select'; + +/* eslint-disable indent */ function onSubmit(e) { - var form = this; - var localAddress = form.querySelector('#txtLocalAddress').value; - var enableUpnp = form.querySelector('#chkEnableUpnp').checked; + const form = this; + const localAddress = form.querySelector('#txtLocalAddress').value; + const enableUpnp = form.querySelector('#chkEnableUpnp').checked; confirmSelections(localAddress, enableUpnp, function () { - var validationResult = getValidationAlert(form); + const validationResult = getValidationAlert(form); if (validationResult) { showAlertText(validationResult); @@ -15,7 +19,7 @@ define(['loading', 'libraryMenu', 'globalize', 'emby-checkbox', 'emby-select'], validateHttps(form).then(function () { loading.show(); - ApiClient.getServerConfiguration().then(function (config) { + ApiClient.getNamedConfiguration('network').then(function (config) { config.LocalNetworkSubnets = form.querySelector('#txtLanNetworks').value.split(',').map(function (s) { return s.trim(); }).filter(function (s) { @@ -26,7 +30,24 @@ define(['loading', 'libraryMenu', 'globalize', 'emby-checkbox', 'emby-select'], }).filter(function (s) { return s.length > 0; }); - config.IsRemoteIPFilterBlacklist = 'blacklist' === form.querySelector('#selectExternalAddressFilterMode').value; + config.KnownProxies = form.querySelector('#txtKnownProxies').value.split(',').map(function (s) { + return s.trim(); + }).filter(function (s) { + return s.length > 0; + }); + config.LocalNetworkAddresses = form.querySelector('#txtLocalAddress').value.split(',').map(function (s) { + return s.trim(); + }).filter(function (s) { + return s.length > 0; + }); + + config.PublishedServerUriBySubnet = form.querySelector('#txtPublishedServer').value.split(',').map(function (s) { + return s.trim(); + }).filter(function (s) { + return s.length > 0; + }); + + config.IsRemoteIPFilterBlacklist = form.querySelector('#selectExternalAddressFilterMode').value === 'blacklist'; config.PublicPort = form.querySelector('#txtPublicPort').value; config.PublicHttpsPort = form.querySelector('#txtPublicHttpsPort').value; config.HttpServerPortNumber = form.querySelector('#txtPortNumber').value; @@ -38,8 +59,18 @@ define(['loading', 'libraryMenu', 'globalize', 'emby-checkbox', 'emby-select'], config.EnableRemoteAccess = form.querySelector('#chkRemoteAccess').checked; config.CertificatePath = form.querySelector('#txtCertificatePath').value || null; config.CertificatePassword = form.querySelector('#txtCertPassword').value || null; - config.LocalNetworkAddresses = localAddress ? [localAddress] : []; - ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult, Dashboard.processErrorResponse); + + config.UPnPCreateHttpPortMap = form.querySelector('#chkCreateHttpPortMap').checked; + config.AutoDiscovery = form.querySelector('#chkAutodiscovery').checked; + config.AutoDiscoveryTracing = form.querySelector('#chkAutodiscoveryTracing').checked; + config.EnableIP6 = form.querySelector('#chkEnableIP6').checked; + config.EnableIP4 = form.querySelector('#chkEnableIP4').checked; + config.UPnPCreateHttpPortMap = form.querySelector('#chkCreateHttpPortMap').checked; + config.UDPPortRange = form.querySelector('#txtUDPPortRange').value || null; + config.HDHomerunPortRange = form.querySelector('#txtHDHomerunPortRange').checked || null; + config.EnableSSDPTracing = form.querySelector('#chkEnableSSDPTracing').checked; + config.SSDPTracingFilter = form.querySelector('#txtSSDPTracingFilter').value || null; + ApiClient.updateNamedConfiguration('network', config).then(Dashboard.processServerConfigurationUpdateResult, Dashboard.processErrorResponse); }); }); }); @@ -47,7 +78,7 @@ define(['loading', 'libraryMenu', 'globalize', 'emby-checkbox', 'emby-select'], } function triggerChange(select) { - var evt = document.createEvent('HTMLEvents'); + const evt = document.createEvent('HTMLEvents'); evt.initEvent('change', false, true); select.dispatchEvent(evt); } @@ -65,8 +96,8 @@ define(['loading', 'libraryMenu', 'globalize', 'emby-checkbox', 'emby-select'], } function validateHttps(form) { - var certPath = form.querySelector('#txtCertificatePath').value || null; - var httpsEnabled = form.querySelector('#chkEnableHttps').checked; + const certPath = form.querySelector('#txtCertificatePath').value || null; + const httpsEnabled = form.querySelector('#chkEnableHttps').checked; if (httpsEnabled && !certPath) { return showAlertText({ @@ -80,7 +111,7 @@ define(['loading', 'libraryMenu', 'globalize', 'emby-checkbox', 'emby-select'], function showAlertText(options) { return new Promise(function (resolve, reject) { - require(['alert'], function (alert) { + import('alert').then(({default: alert}) => { alert(options).then(resolve, reject); }); }); @@ -97,25 +128,37 @@ define(['loading', 'libraryMenu', 'globalize', 'emby-checkbox', 'emby-select'], } } - return function (view, params) { + export default function (view, params) { function loadPage(page, config) { page.querySelector('#txtPortNumber').value = config.HttpServerPortNumber; page.querySelector('#txtPublicPort').value = config.PublicPort; page.querySelector('#txtPublicHttpsPort').value = config.PublicHttpsPort; page.querySelector('#txtLocalAddress').value = config.LocalNetworkAddresses[0] || ''; page.querySelector('#txtLanNetworks').value = (config.LocalNetworkSubnets || []).join(', '); + page.querySelector('#txtKnownProxies').value = (config.KnownProxies || []).join(', '); page.querySelector('#txtExternalAddressFilter').value = (config.RemoteIPFilter || []).join(', '); page.querySelector('#selectExternalAddressFilterMode').value = config.IsRemoteIPFilterBlacklist ? 'blacklist' : 'whitelist'; - page.querySelector('#chkRemoteAccess').checked = null == config.EnableRemoteAccess || config.EnableRemoteAccess; + page.querySelector('#chkRemoteAccess').checked = config.EnableRemoteAccess == null || config.EnableRemoteAccess; page.querySelector('#txtHttpsPort').value = config.HttpsPortNumber; page.querySelector('#chkEnableHttps').checked = config.EnableHttps; page.querySelector('#chkRequireHttps').checked = config.RequireHttps; page.querySelector('#txtBaseUrl').value = config.BaseUrl || ''; - var txtCertificatePath = page.querySelector('#txtCertificatePath'); + const txtCertificatePath = page.querySelector('#txtCertificatePath'); txtCertificatePath.value = config.CertificatePath || ''; page.querySelector('#txtCertPassword').value = config.CertificatePassword || ''; page.querySelector('#chkEnableUpnp').checked = config.EnableUPnP; triggerChange(page.querySelector('#chkRemoteAccess')); + form.querySelector('#chkCreateHttpPortMap').checked = config.UPnPCreateHttpPortMap; + form.querySelector('#chkAutodiscovery').checked = config.AutoDiscovery; + form.querySelector('#chkAutodiscoveryTracing').checked = config.AutoDiscoveryTracing; + form.querySelector('#chkEnableIP6').checked = config.EnableIP6; + form.querySelector('#chkEnableIP4').checked = config.EnableIP4; + form.querySelector('#chkCreateHttpPortMap').checked = config.UPnPCreateHttpPortMap; + form.querySelector('#txtUDPPortRange').value = config.UDPPortRange; + form.querySelector('#txtHDHomerunPortRange').checked = config.HDHomerunPortRange; + form.querySelector('#chkEnableSSDPTracing').checked = config.EnableSSDPTracing; + form.querySelector('#txtSSDPTracingFilter').value = config.SSDPTracingFilter; + loading.hide(); } @@ -135,8 +178,8 @@ define(['loading', 'libraryMenu', 'globalize', 'emby-checkbox', 'emby-select'], } }); view.querySelector('#btnSelectCertPath').addEventListener('click', function () { - require(['directorybrowser'], function (directoryBrowser) { - var picker = new directoryBrowser(); + import('directorybrowser').then(({default: directoryBrowser}) => { + const picker = new directoryBrowser(); picker.show({ includeFiles: true, includeDirectories: true, @@ -154,9 +197,10 @@ define(['loading', 'libraryMenu', 'globalize', 'emby-checkbox', 'emby-select'], view.querySelector('.dashboardHostingForm').addEventListener('submit', onSubmit); view.addEventListener('viewshow', function (e) { loading.show(); - ApiClient.getServerConfiguration().then(function (config) { + ApiClient.getNamedConfiguration('network').then(function (config) { loadPage(view, config); }); }); - }; -}); + } + +/* eslint-enable indent */ From a52c13fa5350ff6acb4f84590bb7df468aa1f0ba Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sat, 10 Oct 2020 13:22:30 +0100 Subject: [PATCH 020/202] Add files via upload https://github.com/jellyfin/jellyfin/pull/4124 --- src/strings/en-gb.json | 3028 +++++++++++++++++++--------------------- src/strings/en-us.json | 3017 +++++++++++++++++++-------------------- 2 files changed, 2897 insertions(+), 3148 deletions(-) diff --git a/src/strings/en-gb.json b/src/strings/en-gb.json index 8b63def2a2..bf219bb07d 100644 --- a/src/strings/en-gb.json +++ b/src/strings/en-gb.json @@ -1,1583 +1,1449 @@ { - "AdditionalNotificationServices": "Browse the plugin catalogue to install additional notification services.", - "BrowsePluginCatalogMessage": "Browse our plugin catalogue to view available plugins.", - "CinemaModeConfigurationHelp": "Cinema mode brings the theatre experience straight to your living room with the ability to play trailers and custom intros before the main feature.", - "ColorPrimaries": "Colour primaries", - "ColorSpace": "Colour space", - "ColorTransfer": "Colour transfer", - "DefaultMetadataLangaugeDescription": "These are your defaults and can be customized on a per-library basis.", - "EnableColorCodedBackgrounds": "Colour coded backgrounds", - "Favorite": "Favourite", - "Favorites": "Favourites", - "HDPrograms": "HD programs", - "HeaderBlockItemsWithNoRating": "Block items with no or unrecognized rating information:", - "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.", - "ImportFavoriteChannelsHelp": "If enabled, only channels that are marked as favourite on the tuner device will be imported.", - "LabelDateAddedBehavior": "Date added behaviour for new content:", - "LabelImportOnlyFavoriteChannels": "Restrict to channels marked as favourite", - "LabelKodiMetadataUserHelp": "Save watch data to NFO files for other applications to utilize.", - "LabelTextBackgroundColor": "Text background color:", - "LabelTextColor": "Text color:", - "NewCollectionHelp": "Collections allow you to create personalized groupings of movies and other library content.", - "NoNewDevicesFound": "No new devices found. To add a new tuner, close this dialogueand enter the device information manually.", - "OptionEnableExternalContentInSuggestionsHelp": "Allow internet trailers and live TV programs to be included within suggested content.", - "OptionFavorite": "Favourites", - "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honoured but will ignore the byte range header.", - "PlaceFavoriteChannelsAtBeginning": "Place favourite channels at the beginning", - "Programs": "Programs", - "TabCatalog": "Catalogue", - "TabFavorites": "Favourites", - "XmlTvKidsCategoriesHelp": "Programs with these categories will be displayed as programs for children. Separate multiple with '|'.", - "XmlTvMovieCategoriesHelp": "Programs with these categories will be displayed as movies. Separate multiple with '|'.", - "XmlTvNewsCategoriesHelp": "Programs with these categories will be displayed as news programs. Separate multiple with '|'.", - "XmlTvSportsCategoriesHelp": "Programs with these categories will be displayed as sports programs. Separate multiple with '|'.", - "Albums": "Albums", - "Artists": "Artists", - "Books": "Books", - "Channels": "Channels", - "Collections": "Collections", - "Folders": "Folders", - "Genres": "Genres", - "HeaderAlbumArtists": "Album Artists", - "HeaderContinueWatching": "Continue Watching", - "HeaderLiveTV": "Live TV", - "HeaderNextUp": "Next Up", - "Movies": "Movies", - "Photos": "Photos", - "Playlists": "Playlists", - "Shows": "Shows", - "Songs": "Songs", - "Sync": "Sync", - "ValueSpecialEpisodeName": "Special - {0}", - "Absolute": "Absolute", - "AccessRestrictedTryAgainLater": "Access is currently restricted. Please try again later.", - "Actor": "Actor", - "Add": "Add", - "AddItemToCollectionHelp": "Add items to collections by searching for them and using their right-click or tap menus to add them to a collection.", - "AddToCollection": "Add to collection", - "AddToPlayQueue": "Add to play queue", - "AddToPlaylist": "Add to playlist", - "AddedOnValue": "Added {0}", - "AirDate": "Air date", - "Aired": "Aired", - "Alerts": "Alerts", - "All": "All", - "AllChannels": "All channels", - "AllComplexFormats": "All Complex Formats (ASS, SSA, VOBSUB, PGS, SUB, IDX, …)", - "AllEpisodes": "All episodes", - "AllLanguages": "All languages", - "AllLibraries": "All libraries", - "AllowHWTranscodingHelp": "Allow the tuner to transcode streams on the fly. This may help reduce transcoding required by the server.", - "AllowMediaConversion": "Allow media conversion", - "AllowMediaConversionHelp": "Grant or deny access to the convert media feature.", - "AllowOnTheFlySubtitleExtraction": "Allow subtitle extraction on the fly", - "AllowOnTheFlySubtitleExtractionHelp": "Embedded subtitles can be extracted from videos and delivered to clients in plain text, in order to help prevent video transcoding. On some systems this can take a long time and cause video playback to stall during the extraction process. Disable this to have embedded subtitles burned in with video transcoding when they are not natively supported by the client device.", - "AllowRemoteAccess": "Allow remote connections to this Jellyfin Server.", - "AllowRemoteAccessHelp": "If unchecked, all remote connections will be blocked.", - "AllowedRemoteAddressesHelp": "Comma separated list of IP addresses or IP/netmask entries for networks that will be allowed to connect remotely. If left blank, all remote addresses will be allowed.", - "AlwaysPlaySubtitles": "Always Play", - "AlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.", - "AnyLanguage": "Any Language", - "Anytime": "Anytime", - "AroundTime": "Around", - "Art": "Art", - "AsManyAsPossible": "As many as possible", - "Ascending": "Ascending", - "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", - "Backdrops": "Backdrops", - "Banner": "Banner", - "BirthDateValue": "Born: {0}", - "BirthLocation": "Birth location", - "BirthPlaceValue": "Birth place: {0}", - "Blacklist": "Blacklist", - "BookLibraryHelp": "Audio and text books are supported. Review the {0} book naming guide {1}.", - "Box": "Box", - "BoxRear": "Box (rear)", - "Browse": "Browse", - "BurnSubtitlesHelp": "Determines if the server should burn in subtitles when transcoding videos. Avoiding this will greatly improve performance. Select Auto to burn image based formats (VOBSUB, PGS, SUB, IDX, …) and certain ASS or SSA subtitles.", - "ButtonAdd": "Add", - "ButtonAddMediaLibrary": "Add Media Library", - "ButtonAddScheduledTaskTrigger": "Add Trigger", - "ButtonAddServer": "Add Server", - "ButtonAddUser": "Add User", - "ButtonArrowDown": "Down", - "ButtonArrowLeft": "Left", - "ButtonArrowRight": "Right", - "ButtonArrowUp": "Up", - "ButtonAudioTracks": "Audio Tracks", - "ButtonBack": "Back", - "ButtonCancel": "Cancel", - "ButtonChangeContentType": "Change content type", - "ButtonChangeServer": "Change Server", - "ButtonConnect": "Connect", - "ButtonDelete": "Delete", - "ButtonDeleteImage": "Delete Image", - "ButtonDown": "Down", - "ButtonDownload": "Download", - "ButtonEdit": "Edit", - "ButtonEditImages": "Edit images", - "ButtonEditOtherUserPreferences": "Edit this user's profile, image and personal preferences.", - "ButtonFilter": "Filter", - "ButtonForgotPassword": "Forgot Password", - "ButtonFullscreen": "Fullscreen", - "ButtonGotIt": "Got It", - "ButtonGuide": "Guide", - "ButtonHelp": "Help", - "ButtonHome": "Home", - "ButtonInfo": "Info", - "ButtonLearnMore": "Learn more", - "ButtonLibraryAccess": "Library access", - "ButtonManualLogin": "Manual Login", - "ButtonMore": "More", - "ButtonMoreInformation": "More Information", - "ButtonNetwork": "Network", - "ButtonNew": "New", - "ButtonNextTrack": "Next track", - "ButtonOff": "Off", - "ButtonOk": "OK", - "ButtonOpen": "Open", - "ButtonParentalControl": "Parental control", - "ButtonPause": "Pause", - "ButtonPlay": "Play", - "ButtonPreviousTrack": "Previous track", - "ButtonProfile": "Profile", - "ButtonQuickStartGuide": "Quick Start Guide", - "ButtonRefresh": "Refresh", - "ButtonRefreshGuideData": "Refresh Guide Data", - "ButtonRemove": "Remove", - "ButtonRename": "Rename", - "ButtonRepeat": "Repeat", - "ButtonResetEasyPassword": "Reset easy pin code", - "ButtonResetPassword": "Reset Password", - "ButtonRestart": "Restart", - "ButtonResume": "Resume", - "ButtonRevoke": "Revoke", - "ButtonSave": "Save", - "ButtonScanAllLibraries": "Scan All Libraries", - "ButtonSearch": "Search", - "ButtonSelectDirectory": "Select Directory", - "ButtonSelectServer": "Select Server", - "ButtonSelectView": "Select view", - "ButtonSend": "Send", - "ButtonSettings": "Settings", - "ButtonShuffle": "Shuffle", - "ButtonShutdown": "Shutdown", - "ButtonSignIn": "Sign In", - "ButtonSignOut": "Sign Out", - "ButtonSort": "Sort", - "ButtonStart": "Start", - "ButtonStop": "Stop", - "ButtonSubmit": "Submit", - "ButtonSubtitles": "Subtitles", - "ButtonTrailer": "Trailer", - "ButtonUninstall": "Uninstall", - "ButtonUp": "Up", - "ButtonViewWebsite": "View website", - "ButtonWebsite": "Website", - "CancelRecording": "Cancel recording", - "CancelSeries": "Cancel series", - "Categories": "Categories", - "ChangingMetadataImageSettingsNewContent": "Changes to metadata or artwork downloading settings will only apply to new content added to your library. To apply the changes to existing titles, you'll need to refresh their metadata manually.", - "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.", - "ChannelNameOnly": "Channel {0} only", - "ChannelNumber": "Channel number", - "CommunityRating": "Community rating", - "Composer": "Composer", - "ConfigureDateAdded": "Configure how date added is determined in the Jellyfin Server dashboard under Library settings", - "ConfirmDeleteImage": "Delete image?", - "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?", - "ConfirmDeleteItems": "Deleting these items will delete them from both the file system and your media library. Are you sure you wish to continue?", - "ConfirmDeletion": "Confirm Deletion", - "ConfirmEndPlayerSession": "Would you like to shutdown Jellyfin on {0}?", - "Connect": "Connect", - "ContinueWatching": "Continue watching", - "Continuing": "Continuing", - "CriticRating": "Critic rating", - "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.", - "DateAdded": "Date added", - "DatePlayed": "Date played", - "DeathDateValue": "Died: {0}", - "Default": "Default", - "DefaultErrorMessage": "There was an error processing the request. Please try again later.", - "DefaultSubtitlesHelp": "Subtitles are loaded based on the default and forced flags in the embedded metadata. Language preferences are considered when multiple options are available.", - "Delete": "Delete", - "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", - "DeleteImage": "Delete Image", - "DeleteImageConfirmation": "Are you sure you wish to delete this image?", - "DeleteMedia": "Delete media", - "DeleteUser": "Delete User", - "DeleteUserConfirmation": "Are you sure you wish to delete this user?", - "Depressed": "Depressed", - "Descending": "Descending", - "Desktop": "Desktop", - "DetectingDevices": "Detecting devices", - "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", - "DirectPlaying": "Direct playing", - "DirectStreamHelp1": "The media is compatible with the device regarding resolution and media type (H.264, AC3, etc), but is in an incompatible file container (mkv, avi, wmv, etc). The video will be re-packaged on the fly before streaming it to the device.", - "DirectStreamHelp2": "Direct Streaming a file uses very little processing power without any loss in video quality.", - "DirectStreaming": "Direct streaming", - "Director": "Director", - "Directors": "Directors", - "Disabled": "Disabled", - "Disc": "Disc", - "Disconnect": "Disconnect", - "Dislike": "Dislike", - "Display": "Display", - "DisplayInMyMedia": "Display on home screen", - "DisplayInOtherHomeScreenSections": "Display in home screen sections such as latest media and continue watching", - "DisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", - "DisplayMissingEpisodesWithinSeasonsHelp": "This must also be enabled for TV libraries in the server configuration.", - "DisplayModeHelp": "Select the layout style you want for the interface.", - "DoNotRecord": "Do not record", - "Down": "Down", - "Download": "Download", - "DownloadsValue": "{0} downloads", - "DrmChannelsNotImported": "Channels with DRM will not be imported.", - "DropShadow": "Drop Shadow", - "EasyPasswordHelp": "Your easy pin code is used for offline access on supported clients and can also be used for easy in-network sign in.", - "Edit": "Edit", - "EditImages": "Edit images", - "EditMetadata": "Edit metadata", - "EditSubtitles": "Edit subtitles", - "EnableBackdrops": "Backdrops", - "EnableBackdropsHelp": "Display backdrops in the background of some pages while browsing the library.", - "EnableCinemaMode": "Cinema mode", - "EnableDebugLoggingHelp": "Debug logging should only be enabled as needed for troubleshooting purposes. The increased file system access may prevent the server machine from being able to sleep in some environments.", - "EnableDisplayMirroring": "Display mirroring", - "EnableExternalVideoPlayers": "External video players", - "EnableExternalVideoPlayersHelp": "An external player menu will be shown when starting video playback.", - "EnableHardwareEncoding": "Enable hardware encoding", - "EnableNextVideoInfoOverlay": "Show next video info during playback", - "EnableNextVideoInfoOverlayHelp": "At the end of a video, display info about the next video coming up in the current playlist.", - "EnablePhotos": "Display photos", - "EnablePhotosHelp": "Images will be detected and displayed alongside other media files.", - "EnableStreamLooping": "Auto-loop live streams", - "EnableStreamLoopingHelp": "Enable this if live streams only contain a few seconds of data and need to be continuously requested. Enabling this when not needed may cause problems.", - "EnableThemeSongs": "Theme songs", - "EnableThemeSongsHelp": "Play theme songs in the background while browsing the library.", - "EnableThemeVideos": "Theme videos", - "EnableThemeVideosHelp": "Play theme videos in the background while browsing the library.", - "Ended": "Ended", - "EndsAtValue": "Ends at {0}", - "Episodes": "Episodes", - "ErrorAddingListingsToSchedulesDirect": "There was an error adding the lineup to your Schedules Direct account. Schedules Direct only allows a limited number of lineups per account. You may need to log into the Schedules Direct website and remove others listings from your account before proceeding.", - "ErrorAddingMediaPathToVirtualFolder": "There was an error adding the media path. Please ensure the path is valid and the Jellyfin Server process has access to that location.", - "ErrorAddingTunerDevice": "There was an error adding the tuner device. Please ensure it is accessible and try again.", - "ErrorAddingXmlTvFile": "There was an error accessing the XMLTV file. Please ensure the file exists and try again.", - "ErrorDeletingItem": "There was an error deleting the item from Jellyfin Server. Please check that Jellyfin Server has write access to the media folder and try again.", - "ErrorGettingTvLineups": "There was an error downloading TV lineups. Please ensure your information is correct and try again.", - "ErrorMessageStartHourGreaterThanEnd": "End time must be greater than the start time.", - "ErrorPleaseSelectLineup": "Please select a lineup and try again. If no lineups are available, then please check that your username, password, and postal code is correct.", - "ErrorSavingTvProvider": "There was an error saving the TV provider. Please ensure it is accessible and try again.", - "EveryNDays": "Every {0} days", - "ExitFullscreen": "Exit full screen", - "ExtraLarge": "Extra Large", - "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, resource intensive, and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", - "Extras": "Extras", - "FFmpegSavePathNotFound": "We're unable to locate FFmpeg using the path you've entered. FFprobe is also required and must exist in the same folder. These components are normally bundled together in the same download. Please check the path and try again.", - "FastForward": "Fast-forward", - "Features": "Features", - "File": "File", - "FileNotFound": "File not found.", - "FileReadCancelled": "The file read has been cancelled.", - "FileReadError": "An error occurred while reading the file.", - "Filters": "Filters", - "FolderTypeBooks": "Books", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeMusicVideos": "Music Videos", - "FolderTypeTvShows": "TV Shows", - "FolderTypeUnset": "Mixed Content", - "FormatValue": "Format: {0}", - "Friday": "Friday", - "Fullscreen": "Full screen", - "General": "General", - "Genre": "Genre", - "GroupBySeries": "Group by series", - "GroupVersions": "Group versions", - "GuestStar": "Guest star", - "Guide": "Guide", - "GuideProviderLogin": "Login", - "GuideProviderSelectListings": "Select Listings", - "H264CrfHelp": "The Constant Rate Factor (CRF) is the default quality setting for the x264 encoder. You can set the values between 0 and 51, where lower values would result in better quality (at the expense of higher file sizes). Sane values are between 18 and 28. The default for x264 is 23, so you can use this as a starting point.", - "EncoderPresetHelp": "Choose a faster value to improve performance, or a slower value to improve quality.", - "HandledByProxy": "Handled by reverse proxy", - "HardwareAccelerationWarning": "Enabling hardware acceleration may cause instability in some environments. Ensure that your operating system and video drivers are fully up to date. If you have difficulty playing video after enabling this, you'll need to change the setting back to None.", - "HeaderAccessSchedule": "Access Schedule", - "HeaderAccessScheduleHelp": "Create an access schedule to limit access to certain hours.", - "HeaderActiveDevices": "Active Devices", - "HeaderActiveRecordings": "Active Recordings", - "HeaderActivity": "Activity", - "HeaderAddScheduledTaskTrigger": "Add Trigger", - "HeaderAddToCollection": "Add to Collection", - "HeaderAddToPlaylist": "Add to Playlist", - "HeaderAddUpdateImage": "Add/Update Image", - "HeaderAddUser": "Add User", - "HeaderAdditionalParts": "Additional Parts", - "HeaderAdmin": "Admin", - "HeaderAlbums": "Albums", - "HeaderAlert": "Alert", - "HeaderAllowMediaDeletionFrom": "Allow Media Deletion From", - "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 a Jellyfin account, or by manually granting the application a key.", - "HeaderApp": "App", - "HeaderAppearsOn": "Appears On", - "HeaderAudioBooks": "Audio Books", - "HeaderAudioSettings": "Audio Settings", - "HeaderAutomaticUpdates": "Automatic Updates", - "HeaderBooks": "Books", - "HeaderBranding": "Branding", - "HeaderCancelRecording": "Cancel Recording", - "HeaderCancelSeries": "Cancel Series", - "HeaderCastAndCrew": "Cast & Crew", - "HeaderCastCrew": "Cast & Crew", - "HeaderChangeFolderType": "Change Content Type", - "HeaderChangeFolderTypeHelp": "To change the type, please remove and rebuild the library with the new type.", - "HeaderChannelAccess": "Channel Access", - "HeaderChannels": "Channels", - "HeaderChapterImages": "Chapter Images", - "HeaderCodecProfile": "Codec Profile", - "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.", - "HeaderConfigureRemoteAccess": "Configure Remote Access", - "HeaderConfirmPluginInstallation": "Confirm Plugin Installation", - "HeaderConfirmProfileDeletion": "Confirm Profile Deletion", - "HeaderConfirmRevokeApiKey": "Revoke API Key", - "HeaderConnectToServer": "Connect to Server", - "HeaderConnectionFailure": "Connection Failure", - "HeaderContainerProfile": "Container Profile", - "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.", - "HeaderContinueListening": "Continue Listening", - "HeaderCustomDlnaProfiles": "Custom Profiles", - "HeaderDateIssued": "Date Issued", - "HeaderDefaultRecordingSettings": "Default Recording Settings", - "HeaderDeleteDevice": "Delete Device", - "HeaderDeleteItem": "Delete Item", - "HeaderDeleteItems": "Delete Items", - "HeaderDeleteProvider": "Delete Provider", - "HeaderDeleteTaskTrigger": "Delete Task Trigger", - "HeaderDetectMyDevices": "Detect My Devices", - "HeaderDeveloperInfo": "Developer Info", - "HeaderDeviceAccess": "Device Access", - "HeaderDevices": "Devices", - "HeaderDirectPlayProfile": "Direct Play Profile", - "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.", - "HeaderDisplay": "Display", - "HeaderDownloadSync": "Download & Sync", - "HeaderEasyPinCode": "Easy Pin Code", - "HeaderEditImages": "Edit Images", - "HeaderEnabledFields": "Enabled Fields", - "HeaderEnabledFieldsHelp": "Uncheck a field to lock it and prevent its data from being changed.", - "HeaderEpisodes": "Episodes", - "HeaderError": "Error", - "HeaderExternalIds": "External IDs:", - "HeaderFavoriteBooks": "Favourite Books", - "HeaderFavoriteMovies": "Favourite Movies", - "HeaderFavoriteShows": "Favourite Shows", - "HeaderFavoriteEpisodes": "Favourite Episodes", - "HeaderFavoriteAlbums": "Favourite Albums", - "HeaderFavoriteArtists": "Favourite Artists", - "HeaderFavoriteSongs": "Favourite Songs", - "HeaderFavoriteVideos": "Favourite Videos", - "HeaderFavoritePlaylists": "Favourite Playlists", - "HeaderFeatureAccess": "Feature Access", - "HeaderFeatures": "Features", - "HeaderFetchImages": "Fetch Images:", - "HeaderFetcherSettings": "Fetcher Settings", - "HeaderFilters": "Filters", - "HeaderForKids": "For Kids", - "HeaderForgotPassword": "Forgot Password", - "HeaderFrequentlyPlayed": "Frequently Played", - "HeaderGenres": "Genres", - "HeaderGuideProviders": "TV Guide Data Providers", - "HeaderHomeScreen": "Home Screen", - "HeaderHomeScreenSettings": "Home Screen Settings", - "HeaderHttpHeaders": "HTTP Headers", - "HeaderIdentification": "Identification", - "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.", - "HeaderIdentificationHeader": "Identification Header", - "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.", - "HeaderImageOptions": "Image Options", - "HeaderImageSettings": "Image Settings", - "HeaderInstall": "Install", - "HeaderInstantMix": "Instant Mix", - "HeaderItems": "Items", - "HeaderJellyfinServer": "Jellyfin Server", - "HeaderKeepRecording": "Keep Recording", - "HeaderKeepSeries": "Keep Series", - "HeaderKodiMetadataHelp": "To enable or disable NFO metadata, edit a library in Jellyfin library setup and locate the metadata savers section.", - "HeaderLatestEpisodes": "Latest Episodes", - "HeaderLatestMedia": "Latest Media", - "HeaderLatestMovies": "Latest Movies", - "HeaderLatestMusic": "Latest Music", - "HeaderLatestRecordings": "Latest Recordings", - "HeaderLibraries": "Libraries", - "HeaderLibraryAccess": "Library Access", - "HeaderLibraryFolders": "Library Folders", - "HeaderLibraryOrder": "Library Order", - "HeaderLibrarySettings": "Library Settings", - "HeaderLiveTv": "Live TV", - "HeaderLiveTvTunerSetup": "Live TV Tuner Setup", - "HeaderLoginFailure": "Login Failure", - "HeaderMedia": "Media", - "HeaderMediaFolders": "Media Folders", - "HeaderMediaInfo": "Media Info", - "HeaderMetadataSettings": "Metadata Settings", - "HeaderMoreLikeThis": "More Like This", - "HeaderMovies": "Movies", - "HeaderMusicQuality": "Music Quality", - "HeaderMusicVideos": "Music Videos", - "HeaderMyDevice": "My Device", - "HeaderMyMedia": "My Media", - "HeaderMyMediaSmall": "My Media (small)", - "HeaderNewApiKey": "New API Key", - "HeaderNewDevices": "New Devices", - "HeaderNextEpisodePlayingInValue": "Next Episode Playing in {0}", - "HeaderNextVideoPlayingInValue": "Next Video Playing in {0}", - "HeaderOnNow": "On Now", - "HeaderOtherItems": "Other Items", - "HeaderParentalRatings": "Parental Ratings", - "HeaderPassword": "Password", - "HeaderPasswordReset": "Password Reset", - "HeaderPaths": "Paths", - "HeaderPendingInvitations": "Pending Invitations", - "CopyStreamURL": "Copy Stream URL", - "CopyStreamURLSuccess": "URL copied successfully.", - "XmlDocumentAttributeListHelp": "These attributes are applied to the root element of every XML response.", - "Writer": "Writer", - "WizardCompleted": "That's all we need for now. Jellyfin has begun collecting information about your media library. Check out some of our apps, and then click Finish to view the Dashboard.", - "Vertical": "Vertical", - "ValueVideoCodec": "Video Codec: {0}", - "ValueTimeLimitSingleHour": "Time limit: 1 hour", - "ValueTimeLimitMultiHour": "Time limit: {0} hours", - "ValueSeriesCount": "{0} series", - "ValueSeconds": "{0} seconds", - "ValueOneSong": "1 song", - "ValueOneMusicVideo": "1 music video", - "ValueOneAlbum": "1 album", - "ValueMusicVideoCount": "{0} music videos", - "ValueMovieCount": "{0} movies", - "ValueMinutes": "{0} min", - "ValueDiscNumber": "Disc {0}", - "ValueContainer": "Container: {0}", - "ValueConditions": "Conditions: {0}", - "ValueCodec": "Codec: {0}", - "ValueAudioCodec": "Audio Codec: {0}", - "ValueAlbumCount": "{0} albums", - "UserProfilesIntro": "Jellyfin includes support for user profiles with granular display settings, play state, and parental controls.", - "UserAgentHelp": "Supply a custom user-agent HTTP header.", - "Upload": "Upload", - "Unrated": "Unrated", - "Unplayed": "Unplayed", - "Unmute": "Unmute", - "UninstallPluginHeader": "Uninstall Plugin", - "Trailers": "Trailers", - "TrackCount": "{0} tracks", - "TitlePlayback": "Playback", - "TitleHostingSettings": "Hosting Settings", - "TitleHardwareAcceleration": "Hardware Acceleration", - "Thursday": "Thursday", - "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process. To begin, please select your preferred language.", - "TheseSettingsAffectSubtitlesOnThisDevice": "These settings affect subtitles on this device", - "TabShows": "Shows", - "TabSettings": "Settings", - "TabServer": "Server", - "TabSeries": "Series", - "TabScheduledTasks": "Scheduled Tasks", - "TabResumeSettings": "Resume", - "TabResponses": "Responses", - "TabRecordings": "Recordings", - "TabPlaylist": "Playlist", - "TabPlayback": "Playback", - "TabOther": "Other", - "TabNotifications": "Notifications", - "TabNetworks": "Networks", - "TabMyPlugins": "My Plugins", - "TabMusicVideos": "Music Videos", - "TabMusic": "Music", - "TabMovies": "Movies", - "TabMetadata": "Metadata", - "TabLogs": "Logs", - "TabDisplay": "Display", - "TabDirectPlay": "Direct Play", - "TabDevices": "Devices", - "TabChannels": "Channels", - "TabArtists": "Artists", - "TabAlbums": "Albums", - "TabAlbumArtists": "Album Artists", - "TabAdvanced": "Advanced", - "TabAccess": "Access", - "TV": "TV", - "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.", - "Sunday": "Sunday", - "Suggestions": "Suggestions", - "Subtitles": "Subtitles", - "SubtitleOffset": "Subtitle Offset", - "SubtitleDownloadersHelp": "Enable and rank your preferred subtitle downloaders in order of priority.", - "SubtitleAppearanceSettingsDisclaimer": "These settings will not apply to graphical subtitles (PGS, DVD, etc) or ASS/SSA subtitles that embed their own styles.", - "SortName": "Sort name", - "SortChannelsBy": "Sort channels by:", - "SortByValue": "Sort by {0}", - "SmartSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.", - "Smart": "Smart", - "SimultaneousConnectionLimitHelp": "The maximum number of allowed simultaneous streams. Enter 0 for no limit.", - "Shuffle": "Shuffle", - "New": "New", - "Filter": "Filter", - "ShowYear": "Show year", - "ShowIndicatorsFor": "Show indicators for:", - "ShowAdvancedSettings": "Show advanced settings", - "Share": "Share", - "SettingsWarning": "Changing these values may cause instability or connectivity failures. If you experience any problems, we recommend changing them back to default.", - "SettingsSaved": "Settings saved.", - "Settings": "Settings", - "ServerUpdateNeeded": "This Jellyfin Server needs to be updated. To download the latest version, please visit {0}", - "ServerRestartNeededAfterPluginInstall": "Jellyfin Server will need to be restarted after installing a plugin.", - "ServerNameIsShuttingDown": "Jellyfin Server - {0} is shutting down.", - "SeriesYearToPresent": "{0} - Present", - "SeriesSettings": "Series settings", - "SeriesRecordingScheduled": "Series recording scheduled.", - "SeriesCancelled": "Series cancelled.", - "SendMessage": "Send message", - "SearchResults": "Search Results", - "SearchForSubtitles": "Search for Subtitles", - "SearchForMissingMetadata": "Search for missing metadata", - "Search": "Search", - "Screenshots": "Screenshots", - "Screenshot": "Screenshot", - "Schedule": "Schedule", - "ScanLibrary": "Scan library", - "ScanForNewAndUpdatedFiles": "Scan for new and updated files", - "SaveSubtitlesIntoMediaFoldersHelp": "Storing subtitles next to video files will allow them to be more easily managed.", - "SaveSubtitlesIntoMediaFolders": "Save subtitles into media folders", - "Saturday": "Saturday", - "Runtime": "Runtime", - "RunAtStartup": "Run at startup", - "Rewind": "Rewind", - "ResumeAt": "Resume from {0}", - "RequiredForAllRemoteConnections": "Required for all remote connections", - "ReplaceExistingImages": "Replace existing images", - "ReplaceAllMetadata": "Replace all metadata", - "RepeatOne": "Repeat one", - "RepeatMode": "Repeat Mode", - "RepeatEpisodes": "Repeat episodes", - "RepeatAll": "Repeat all", - "Repeat": "Repeat", - "RemoveFromPlaylist": "Remove from playlist", - "RemoveFromCollection": "Remove from collection", - "RememberMe": "Remember Me", - "ReleaseDate": "Release date", - "RefreshMetadata": "Refresh metadata", - "RefreshDialogHelp": "Metadata is refreshed based on settings and internet services that are enabled in the Jellyfin Server dashboard.", - "Refresh": "Refresh", - "Recordings": "Recordings", - "RecordingScheduled": "Recording scheduled.", - "RecordingPathChangeMessage": "Changing your recording folder will not migrate existing recordings from the old location to the new. You'll need to move them manually if desired.", - "RecordingCancelled": "Recording cancelled.", - "RecordSeries": "Record series", - "Record": "Record", - "RecommendationStarring": "Starring {0}", - "RecommendationDirectedBy": "Directed by {0}", - "RecommendationBecauseYouWatched": "Because you watched {0}", - "Rate": "Rate", - "Raised": "Raised", - "QueueAllFromHere": "Queue all from here", - "Quality": "Quality", - "Producer": "Producer", - "Primary": "Primary", - "Previous": "Previous", - "Premieres": "Premieres", - "Premiere": "Premiere", - "PreferredNotRequired": "Preferred, but not required", - "PreferEmbeddedTitlesOverFileNamesHelp": "This determines the default display title when no internet metadata or local metadata is available.", - "PreferEmbeddedTitlesOverFileNames": "Prefer embedded titles over filenames", - "PluginInstalledMessage": "The plugin has been successfully installed. Jellyfin Server will need to be restarted for changes to take effect.", - "PleaseSelectTwoItems": "Please select at least two items.", - "PleaseRestartServerName": "Please restart Jellyfin Server - {0}.", - "PleaseConfirmPluginInstallation": "Please click OK to confirm you've read the above and wish to proceed with the plugin installation.", - "PleaseAddAtLeastOneFolder": "Please add at least one folder to this library by clicking the Add button.", - "Played": "Played", - "PlayNextEpisodeAutomatically": "Play next episode automatically", - "PlayNext": "Play next", - "PlayFromBeginning": "Play from beginning", - "PlayCount": "Play count", - "PlaybackData": "Playback Data", - "PlayAllFromHere": "Play all from here", - "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", - "PinCodeResetComplete": "The pin code has been reset.", - "PictureInPicture": "Picture in picture", - "PerfectMatch": "Perfect match", - "PasswordSaved": "Password saved.", - "PasswordResetHeader": "Reset Password", - "PasswordResetConfirmation": "Are you sure you wish to reset the password?", - "PasswordResetComplete": "The password has been reset.", - "PasswordMatchError": "Password and password confirmation must match.", - "ParentalRating": "Parental rating", - "PackageInstallFailed": "{0} (version {1}) installation failed.", - "PackageInstallCompleted": "{0} (version {1}) installation completed.", - "PackageInstallCancelled": "{0} (version {1}) installation cancelled.", - "OriginalAirDateValue": "Original air date: {0}", - "OptionWeekly": "Weekly", - "OptionWeekends": "Weekends", - "OptionWeekdays": "Weekdays", - "OptionWednesday": "Wednesday", - "OptionWakeFromSleep": "Wake from sleep", - "OptionUnplayed": "Unplayed", - "OptionUnairedEpisode": "Unaired Episodes", - "OptionTrackName": "Track Name", - "OptionThumbCard": "Thumb card", - "OptionThumb": "Thumb", - "OptionThursday": "Thursday", - "OptionSunday": "Sunday", - "OptionSubstring": "Substring", - "OptionSpecialEpisode": "Specials", - "OptionSaveMetadataAsHiddenHelp": "Changing this will apply to new metadata saved going forward. Existing metadata files will be updated the next time they are saved by Jellyfin Server.", - "OptionSaveMetadataAsHidden": "Save metadata and images as hidden files", - "OptionSaturday": "Saturday", - "OptionRuntime": "Runtime", - "OptionResumable": "Resumable", - "OptionResElement": "res element", - "OptionRequirePerfectSubtitleMatchHelp": "Requiring a perfect match will filter subtitles to include only those that have been tested and verified with your exact video file. Unchecking this will increase the likelihood of subtitles being downloaded, but will increase the chances of mistimed or incorrect subtitle text.", - "OptionRequirePerfectSubtitleMatch": "Only download subtitles that are a perfect match for my video files", - "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.", - "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding", - "OptionRegex": "Regex", - "OptionProfileVideo": "Video", - "OptionProfileAudio": "Audio", - "OptionPremiereDate": "Premiere Date", - "OptionPlayCount": "Play Count", - "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".", - "OptionPlainVideoItems": "Display all videos as plain video items", - "OptionPlainStorageFoldersHelp": "If enabled, all folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".", - "OptionParentalRating": "Parental Rating", - "OptionOnInterval": "On an interval", - "OptionOnAppStartup": "On application startup", - "OptionNone": "None", - "OptionNew": "New…", - "OptionMissingEpisode": "Missing Episodes", - "OptionMax": "Max", - "OptionLoginAttemptsBeforeLockoutHelp": "A value of zero means inheriting the default of three attempts for normal users and five for administrators. Setting this to -1 will disable the feature.", - "OptionLoginAttemptsBeforeLockout": "Determines how many incorrect login attempts can be made before lockout occurs.", - "OptionList": "List", - "OptionDatePlayed": "Date Played", - "OptionBlockTvShows": "TV Shows", - "OptionBlockTrailers": "Trailers", - "OptionBlockMovies": "Movies", - "OptionBlockChannelContent": "Internet Channel Content", - "OptionBanner": "Banner", - "OptionAutomaticallyGroupSeriesHelp": "If enabled, series that are spread across multiple folders within this library will be automatically merged into a single series.", - "OptionAutomaticallyGroupSeries": "Automatically merge series that are spread across multiple folders", - "OptionArtist": "Artist", - "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding", - "OptionAllowVideoPlaybackRemuxing": "Allow video playback that requires conversion without re-encoding", - "OptionAllowUserToManageServer": "Allow this user to manage the server", - "OptionAllowSyncTranscoding": "Allow media downloading and syncing that requires transcoding", - "OptionAllowRemoteSharedDevicesHelp": "DLNA devices are considered shared until a user begins controlling them.", - "OptionAllowRemoteSharedDevices": "Allow remote control of shared devices", - "OptionAllowRemoteControlOthers": "Allow remote control of other users", - "OptionAllowMediaPlaybackTranscodingHelp": "Restricting access to transcoding may cause playback failures in Jellyfin apps due to unsupported media formats.", - "OptionAllowManageLiveTv": "Allow Live TV recording management", - "OptionAllowLinkSharingHelp": "Only web pages containing media information are shared. Media files are never shared publicly. Shares are time-limited and will expire after {0} days.", - "OptionAllowLinkSharing": "Allow social media sharing", - "OptionAllowContentDownloading": "Allow media downloading and syncing", - "OptionAllowBrowsingLiveTv": "Allow Live TV access", - "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding", - "OptionAllUsers": "All users", - "OptionAlbumArtist": "Album Artist", - "OptionAlbum": "Album", - "Option3D": "3D", - "OnlyImageFormats": "Only Image Formats (VOBSUB, PGS, SUB)", - "OnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.", - "Normal": "Normal", - "None": "None", - "NoSubtitlesHelp": "Subtitles will not be loaded by default. They can still be turned on manually during playback.", - "NoSubtitles": "None", - "NoPluginConfigurationMessage": "This plugin has no settings to configure.", - "NoNextUpItemsMessage": "None found. Start watching your shows!", - "No": "No", - "NextUp": "Next Up", - "NewEpisodesOnly": "New episodes only", - "NewCollection": "New Collection", - "Never": "Never", - "MySubtitles": "My Subtitles", - "Mute": "Mute", - "MusicLibraryHelp": "Review the {0}music naming guide{1}.", - "Monday": "Monday", - "MinutesBefore": "minutes before", - "MetadataSettingChangeHelp": "Changing metadata settings will affect new content that is added going forward. To refresh existing content, open the detail screen and click the refresh button, or perform bulk refreshes using the metadata manager.", - "MetadataManager": "Metadata Manager", - "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.", - "MessagePluginConfigurationRequiresLocalAccess": "To configure this plugin please sign in to your local server directly.", - "MessagePleaseWait": "Please wait. This may take a minute.", - "MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.", - "MessagePlayAccessRestricted": "Playback of this content is currently restricted. Please contact your server administrator for more information.", - "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.", - "MessageNothingHere": "Nothing here.", - "MessageNoTrailersFound": "Install the trailers channel to enhance your movie experience by adding a library of internet trailers.", - "MessageNoServersAvailable": "No servers have been found using the automatic server discovery.", - "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", - "MessageNoAvailablePlugins": "No available plugins.", - "MessageInvalidUser": "Invalid username or password. Please try again.", - "MessageInvalidForgotPasswordPin": "An invalid or expired pin code was entered. Please try again.", - "MessageInstallPluginFromApp": "This plugin must be installed from within the app you intend to use it in.", - "MessageImageTypeNotSelected": "Please select an image type from the drop-down menu.", - "MessageImageFileTypeAllowed": "Only JPEG and PNG files are supported.", - "MessageForgotPasswordInNetworkRequired": "Please try again within your home network to initiate the password reset process.", - "MessageForgotPasswordFileCreated": "The following file has been created on your server and contains instructions on how to proceed:", - "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", - "MessageDeleteTaskTrigger": "Are you sure you wish to delete this task trigger?", - "MessageCreateAccountAt": "Create an account at {0}", - "MessageContactAdminToResetPassword": "Please contact your system administrator to reset your password.", - "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Jellyfin Server will be abruptly terminated.", - "MessageConfirmRestart": "Are you sure you wish to restart Jellyfin Server?", - "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?", - "MessageConfirmDeleteTunerDevice": "Are you sure you wish to delete this device?", - "MessageConfirmDeleteGuideProvider": "Are you sure you wish to delete this guide provider?", - "MessageAlreadyInstalled": "This version is already installed.", - "Menu": "Menu", - "MediaIsBeingConverted": "The media is being converted into a format that is compatible with the device that is playing the media.", - "MediaInfoStreamTypeVideo": "Video", - "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", - "MediaInfoStreamTypeAudio": "Audio", - "MediaInfoTimestamp": "Timestamp", - "MediaInfoSize": "Size", - "MediaInfoSampleRate": "Sample rate", - "MediaInfoResolution": "Resolution", - "MediaInfoRefFrames": "Ref frames", - "MediaInfoProfile": "Profile", - "MediaInfoPixelFormat": "Pixel format", - "MediaInfoPath": "Path", - "MediaInfoLevel": "Level", - "MediaInfoLayout": "Layout", - "MediaInfoAspectRatio": "Aspect ratio", - "MediaInfoAnamorphic": "Anamorphic", - "MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.", - "MarkUnplayed": "Mark unplayed", - "MarkPlayed": "Mark played", - "MapChannels": "Map Channels", - "ManageLibrary": "Manage library", - "Logo": "Logo", - "LiveBroadcasts": "Live broadcasts", - "Live": "Live", - "List": "List", - "LibraryAccessHelp": "Select the libraries to share with this user. Administrators will be able to edit all folders using the metadata manager.", - "LeaveBlankToNotSetAPassword": "You can leave this field blank to set no password.", - "LearnHowYouCanContribute": "Learn how you can contribute.", - "LaunchWebAppOnStartupHelp": "Open the web client in your default web browser when the server initially starts. This will not occur when using the restart server function.", - "LanNetworksHelp": "Comma separated list of IP addresses or IP/netmask entries for networks that will be considered on local network when enforcing bandwidth restrictions. If set, all other IP addresses will be considered to be on the external network and will be subject to the external bandwidth restrictions. If left blank, only the server's subnet is considered to be on the local network.", - "LabelffmpegPathHelp": "The path to the ffmpeg application file, or folder containing ffmpeg.", - "LabelffmpegPath": "FFmpeg path:", - "LabelYear": "Year:", - "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.", - "LabelXDlnaDoc": "X-DLNA doc:", - "LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.", - "LabelWeb": "Web:", - "DashboardServerName": "Server: {0}", - "DashboardVersionNumber": "Version: {0}", - "LabelVersionInstalled": "{0} installed", - "LabelVaapiDeviceHelp": "This is the render node that is used for hardware acceleration.", - "LabelVaapiDevice": "VA API Device:", - "LabelUsername": "Username:", - "LabelUserRemoteClientBitrateLimitHelp": "Override the default global value set in server playback settings.", - "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.", - "LabelUserLibrary": "User library:", - "LabelUserAgent": "User agent:", - "LabelUser": "User:", - "LabelUseNotificationServices": "Use the following services:", - "LabelTypeText": "Text", - "LabelTunerIpAddress": "Tuner IP Address:", - "LabelTriggerType": "Trigger Type:", - "LabelTranscodingVideoCodec": "Video codec:", - "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.", - "LabelTranscodingThreadCount": "Transcoding thread count:", - "LabelTranscodingFramerate": "Transcoding framerate:", - "LabelTranscodes": "Transcodes:", - "LabelTranscodingTempPathHelp": "Specify a custom path for the transcode files served to clients. Leave blank to use the server default.", - "LabelTranscodePath": "Transcode path:", - "LabelTranscodingContainer": "Container:", - "LabelTranscodingAudioCodec": "Audio codec:", - "LabelTrackNumber": "Track number:", - "LabelTitle": "Title:", - "LabelTagline": "Tagline:", - "LabelTag": "Tag:", - "LabelTVHomeScreen": "TV mode home screen:", - "LabelSupportedMediaTypes": "Supported Media Types:", - "LabelSubtitles": "Subtitles", - "LabelSubtitlePlaybackMode": "Subtitle mode:", - "LabelSubtitleFormatHelp": "Example: srt", - "LabelSubtitleDownloaders": "Subtitle downloaders:", - "LabelStopping": "Stopping", - "LabelStopWhenPossible": "Stop when possible:", - "LabelStatus": "Status:", - "LabelStartWhenPossible": "Start when possible:", - "LabelSpecialSeasonsDisplayName": "Special season display name:", - "LabelSource": "Source:", - "LabelSoundEffects": "Sound effects:", - "LabelSortBy": "Sort by:", - "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.", - "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery and decrease the likelihood of video transcoding.", - "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.", - "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language", - "LabelSkipBackLength": "Skip back length:", - "LabelSkin": "Skin:", - "LabelSize": "Size:", - "LabelSimultaneousConnectionLimit": "Simultaneous stream limit:", - "LabelServerHost": "Host:", - "LabelSerialNumber": "Serial number", - "LabelSendNotificationToUsers": "Send the notification to:", - "LabelSelectFolderGroupsHelp": "Folders that are unchecked will be displayed by themselves in their own view.", - "LabelSelectFolderGroups": "Automatically group content from the following folders into views such as Movies, Music and TV:", - "LabelSecureConnectionsMode": "Secure connection mode:", - "LabelSeasonNumber": "Season number:", - "LabelScreensaver": "Screensaver:", - "EnableFasterAnimations": "Faster animations", - "EnableFasterAnimationsHelp": "Use faster animations and transitions", - "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", - "LabelSaveLocalMetadataHelp": "Saving artwork into media folders will put them in a place where they can be easily edited.", - "LabelRuntimeMinutes": "Run time (minutes):", - "LabelRemoteClientBitrateLimitHelp": "An optional per-stream bitrate limit for all out of network devices. This is useful to prevent devices from requesting a higher bitrate than your internet connection can handle. This may result in increased CPU load on your server in order to transcode videos on the fly to a lower bitrate.", - "LabelRemoteClientBitrateLimit": "Internet streaming bitrate limit (Mbps):", - "LabelReleaseDate": "Release date:", - "LabelRefreshMode": "Refresh mode:", - "LabelRecord": "Record:", - "LabelReasonForTranscoding": "Reason for transcoding:", - "LabelPublicHttpsPort": "Public HTTPS port number:", - "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local HTTP port.", - "LabelPublicHttpPort": "Public HTTP port number:", - "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.", - "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", - "LabelDidlMode": "DIDL mode:", - "LabelDefaultUser": "Default user:", - "LabelDefaultScreen": "Default screen:", - "LabelDeathDate": "Death date:", - "LabelDay": "Day:", - "LabelDateTimeLocale": "Date time locale:", - "LabelCustomDeviceDisplayNameHelp": "Supply a custom display name or leave empty to use the name reported by the device.", - "HeaderYears": "Years", - "HeaderVideos": "Videos", - "HeaderVideoTypes": "Video Types", - "Series": "Series", - "NewEpisodes": "New episodes", - "NewCollectionNameExample": "Example: Star Wars Collection", - "MinutesAfter": "minutes after", - "Metadata": "Metadata", - "MessageFileReadError": "There was an error reading the file. Please try again.", - "MessageEnablingOptionLongerScans": "Enabling this option may result in significantly longer library scans.", - "MessageConfirmRecordingCancellation": "Cancel recording?", - "MessageConfirmProfileDeletion": "Are you sure you wish to delete this profile?", - "LaunchWebAppOnStartup": "Launch the web interface when starting the server", - "LabelYourFirstName": "Your first name:", - "OnlyForcedSubtitles": "Only Forced", - "Off": "Off", - "NumLocationsValue": "{0} folders", - "Name": "Name", - "MovieLibraryHelp": "Review the {0}movie naming guide{1}.", - "MoveRight": "Move right", - "MoveLeft": "Move left", - "MoreMediaInfo": "Media Info", - "MoreUsersCanBeAddedLater": "More users can be added later from within the dashboard.", - "MoreFromValue": "More from {0}", - "MessageDownloadQueued": "Download queued.", - "MediaInfoStreamTypeData": "Data", - "MediaInfoLanguage": "Language", - "MediaInfoInterlaced": "Interlaced", - "MediaInfoFramerate": "Framerate", - "MediaInfoForced": "Forced", - "MediaInfoExternal": "External", - "MediaInfoDefault": "Default", - "MediaInfoContainer": "Container", - "MediaInfoCodecTag": "Codec tag", - "MediaInfoCodec": "Codec", - "ManageRecording": "Manage recording", - "LiveTV": "Live TV", - "Like": "Like", - "LatestFromLibrary": "Latest {0}", - "Large": "Large", - "LabelZipCode": "Postcode:", - "LabelYoureDone": "You're Done!", - "LabelVideoCodec": "Video codec:", - "LabelVideoBitrate": "Video bitrate:", - "DashboardArchitecture": "Architecture: {0}", - "DashboardOperatingSystem": "Operating System: {0}", - "LabelVersion": "Version:", - "LabelValue": "Value:", - "LabelUserLoginAttemptsBeforeLockout": "Failed login attempts before user is locked out:", - "LabelTranscodingProgress": "Transcoding progress:", - "LabelTimeLimitHours": "Time limit (hours):", - "LabelTime": "Time:", - "LabelTheme": "Theme:", - "LabelTextSize": "Text size:", - "LabelSportsCategories": "Sports categories:", - "LabelSortTitle": "Sort title:", - "LabelSortOrder": "Sort order:", - "LabelSonyAggregationFlags": "Sony aggregation flags:", - "LabelSkipForwardLength": "Skip forward length:", - "LabelSelectUsers": "Select users:", - "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local HTTPS port.", - "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "LabelProtocolInfo": "Protocol info:", - "LabelProfileContainer": "Container:", - "LabelPostProcessorArguments": "Post-processor command line arguments:", - "LabelPlayMethod": "Play method:", - "LabelPlaylist": "Playlist:", - "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language", - "LabelPlaceOfBirth": "Place of birth:", - "LabelOverview": "Overview:", - "LabelOriginalAspectRatio": "Original aspect ratio:", - "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music.", - "LabelMetadataDownloadLanguage": "Preferred download language:", - "LabelMetadata": "Metadata:", - "LabelKeepUpTo": "Keep up to:", - "LabelFinish": "Finish", - "LabelFailed": "Failed", - "LabelExtractChaptersDuringLibraryScan": "Extract chapter images during the library scan", - "LabelEndDate": "End date:", - "LabelEnableSingleImageInDidlLimit": "Limit to single embedded image", - "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging", - "UninstallPluginConfirmation": "Are you sure you wish to uninstall {0}?", - "Uniform": "Uniform", - "TvLibraryHelp": "Review the {0}TV naming guide{1}.", - "Tuesday": "Tuesday", - "Transcoding": "Transcoding", - "ThemeVideos": "Theme videos", - "ThemeSongs": "Theme songs", - "TellUsAboutYourself": "Tell us about yourself", - "TagsValue": "Tags: {0}", - "Tags": "Tags", - "TabUsers": "Users", - "TabUpcoming": "Upcoming", - "TabTranscoding": "Transcoding", - "TabTrailers": "Trailers", - "TabSuggestions": "Suggestions", - "LabelDisplayMode": "Display mode:", - "LabelDisplayLanguageHelp": "Translating Jellyfin is an ongoing project.", - "LabelDisplayLanguage": "Display language:", - "LabelDiscNumber": "Disc number:", - "LabelDeviceDescription": "Device description", - "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.", - "TabStreaming": "Streaming", - "TabSongs": "Songs", - "TabProfiles": "Profiles", - "TabProfile": "Profile", - "TabPlugins": "Plugins", - "TabPlaylists": "Playlists", - "TabNfoSettings": "NFO Settings", - "TabNetworking": "Networking", - "TabLiveTV": "Live TV", - "TabLatest": "Latest", - "TabInfo": "Info", - "TabGuide": "Guide", - "TabGenres": "Genres", - "TabEpisodes": "Episodes", - "TabDashboard": "Dashboard", - "TabContainers": "Containers", - "TabCollections": "Collections", - "TabCodecs": "Codecs", - "Sort": "Sort", - "Smaller": "Smaller", - "SmallCaps": "Small Caps", - "Small": "Small", - "SkipEpisodesAlreadyInMyLibrary": "Don't record episodes that are already in my library", - "RecommendationBecauseYouLike": "Because you like {0}", - "RecentlyWatched": "Recently watched", - "OptionEveryday": "Every day", - "OptionEstimateContentLength": "Estimate content length when transcoding", - "OptionAllowMediaPlayback": "Allow media playback", - "Next": "Next", - "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?", - "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?", - "LabelTypeMetadataDownloaders": "{0} metadata downloaders:", - "LabelType": "Type:", - "LabelTunerType": "Tuner type:", - "LabelServerName": "Server name:", - "LabelServerHostHelp": "192.168.1.100:8096 or https://myserver.com", - "LabelSeriesRecordingPath": "Series recording path (optional):", - "LabelRecordingPathHelp": "Specify the default location to save recordings. If left empty, the server's program data folder will be used.", - "LabelRecordingPath": "Default recording path:", - "LabelReadHowYouCanContribute": "Learn how you can contribute.", - "LabelAlbumArtMaxWidth": "Album art max width:", - "LabelCustomCssHelp": "Apply your own custom styling to the web interface.", - "LabelBlastMessageIntervalHelp": "Determines the duration in seconds between blast alive messages.", - "LabelBlastMessageInterval": "Alive message interval (seconds)", - "LabelBitrate": "Bitrate:", - "LabelAudioSampleRate": "Audio sample rate:", - "LabelAlbumArtMaxHeight": "Album art max height:", - "LabelAccessStart": "Start time:", - "Label3DFormat": "3D format:", - "Thumb": "Thumb", - "ProductionLocations": "Production locations", - "OptionProtocolHttp": "HTTP", - "OptionEnableForAllTuners": "Enable for all tuner devices", - "MessageNoPluginsInstalled": "You have no plugins installed.", - "LabelXDlnaCap": "X-DLNA cap:", - "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains embedded subtitles", - "LabelManufacturer": "Manufacturer:", - "LabelLoginDisclaimer": "Login disclaimer:", - "LabelLocalHttpServerPortNumber": "Local HTTP port number:", - "LabelKodiMetadataEnablePathSubstitution": "Enable path substitution", - "LabelKodiMetadataDateFormatHelp": "All dates within NFO files will be parsed using this format.", - "LabelKodiMetadataDateFormat": "Release date format:", - "LabelKidsCategories": "Children's categories:", - "LabelInNetworkSignInWithEasyPasswordHelp": "Use the easy pin code to sign in to clients within your local network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", - "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", - "LabelHardwareAccelerationTypeHelp": "Hardware acceleration requires additional configuration.", - "LabelEnableHardwareDecodingFor": "Enable hardware decoding for:", - "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play content.", - "LabelEnableDlnaDebugLoggingHelp": "Create large log files and should only be used as needed for troubleshooting purposes.", - "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches performed by Jellyfin.", - "LabelEnableAutomaticPortMapHelp": "Automatically forward public ports on your router to local ports on your server via UPnP. This may not work with some router models or network configurations. Changes will not apply until after a server restart.", - "InstallingPackage": "Installing {0} (version {1})", - "ImportMissingEpisodesHelp": "If enabled, information about missing episodes will be imported into your Jellyfin database and displayed within seasons and series. This may cause significantly longer library scans.", - "HeaderSubtitleAppearance": "Subtitle Appearance", - "LabelProtocol": "Protocol:", - "LabelProfileVideoCodecs": "Video codecs:", - "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.", - "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.", - "LabelProfileAudioCodecs": "Audio codecs:", - "LabelPreferredSubtitleLanguage": "Preferred subtitle language:", - "LabelPreferredDisplayLanguageHelp": "Translating Jellyfin is an ongoing project.", - "LabelPreferredDisplayLanguage": "Preferred display language:", - "LabelPostProcessor": "Post-processing application:", - "LabelPlayer": "Player:", - "LabelPersonRoleHelp": "Example: Ice cream truck driver", - "LabelPersonRole": "Role:", - "LabelPath": "Path:", - "LabelPassword": "Password:", - "LabelParentalRating": "Parental rating:", - "LabelParentNumber": "Parent number:", - "LabelOptionalNetworkPath": "(Optional) Shared network folder:", - "LabelNext": "Next", - "LabelNewsCategories": "News categories:", - "LabelNewPasswordConfirm": "New password confirm:", - "LabelNewPassword": "New password:", - "LabelNewName": "New name:", - "LabelName": "Name:", - "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:", - "LabelMoviePrefix": "Movie prefix:", - "LabelMovieCategories": "Movie categories:", - "LabelMonitorUsers": "Monitor activity from:", - "LabelModelUrl": "Model URL", - "LabelModelNumber": "Model number", - "LabelModelName": "Model name", - "LabelModelDescription": "Model description", - "LabelMinScreenshotDownloadWidth": "Minimum screenshot download width:", - "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time.", - "LabelMinResumePercentage": "Minimum resume percentage:", - "LabelMinResumeDurationHelp": "The shortest video length in seconds that will save playback location and let you resume.", - "LabelMinResumeDuration": "Minimum resume duration:", - "LabelMinBackdropDownloadWidth": "Minimum backdrop download width:", - "LabelMethod": "Method:", - "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.", - "LabelMetadataSavers": "Metadata savers:", - "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.", - "LabelMetadataReaders": "Metadata readers:", - "LabelMetadataPath": "Metadata path:", - "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time.", - "LabelMaxResumePercentage": "Maximum resume percentage:", - "LabelMaxChromecastBitrate": "Chromecast streaming quality:", - "LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:", - "LabelMatchType": "Match type:", - "LabelManufacturerUrl": "Manufacturer URL", - "LabelLoginDisclaimerHelp": "A message that will be displayed at the bottom of the login page.", - "LabelLockItemToPreventChanges": "Lock this item to prevent future changes", - "LabelLocalHttpServerPortNumberHelp": "The TCP port number that Jellyfin's HTTP server should bind to.", - "LabelLineup": "Lineup:", - "LabelLanguage": "Language:", - "LabelLanNetworks": "LAN networks:", - "LabelKodiMetadataUser": "Save user watch data to NFO files for:", - "LabelKodiMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Kodi guidelines.", - "LabelKodiMetadataSaveImagePaths": "Save image paths within nfo files", - "LabelKodiMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.", - "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", - "LabelImageType": "Image type:", - "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.", - "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.", - "LabelIconMaxWidthHelp": "Maximum resolution of icons exposed via upnp:icon.", - "LabelIconMaxWidth": "Icon maximum width:", - "LabelIconMaxHeightHelp": "Maximum resolution of icons exposed via upnp:icon.", - "LabelIconMaxHeight": "Icon maximum height:", - "LabelHttpsPortHelp": "The TCP port number that Jellyfin's HTTPS server should bind to.", - "LabelHttpsPort": "Local HTTPS port number:", - "LabelHomeScreenSectionValue": "Home screen section {0}:", - "LabelHomeNetworkQuality": "Home network quality:", - "LabelHardwareAccelerationType": "Hardware acceleration:", - "LabelEncoderPreset": "H264 and H265 encoding preset:", - "LabelH264Crf": "H264 encoding CRF:", - "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies belonging to a collection will be displayed as one grouped item.", - "LabelGroupMoviesIntoCollections": "Group movies into collections", - "LabelServerNameHelp": "This name will be used to identify the server and will default to the server's computer name.", - "LabelFriendlyName": "Friendly name:", - "LabelFormat": "Format:", - "LabelForgotPasswordUsernameHelp": "Enter your username, if you remember it.", - "LabelFont": "Font:", - "LabelExtractChaptersDuringLibraryScanHelp": "Generate chapter images when videos are imported during the library scan. Otherwise, they will be extracted during the chapter images scheduled task, allowing the regular library scan to complete faster.", - "LabelBaseUrlHelp": "Adds a custom subdirectory to the server URL. For example: http://example.com/<baseurl>", - "LabelEveryXMinutes": "Every:", - "LabelEvent": "Event:", - "LabelEpisodeNumber": "Episode number:", - "LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.", - "LabelEnableRealtimeMonitorHelp": "Changes to files will be processed immediately, on supported file systems.", - "LabelEnableRealtimeMonitor": "Enable real time monitoring", - "LabelEnableDlnaServer": "Enable DLNA server", - "LabelEnableDlnaPlayToHelp": "Detect devices within your network and offer the ability to remote control them.", - "LabelEnableDlnaPlayTo": "Enable DLNA Play To", - "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval (seconds)", - "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.", - "LabelEnableBlastAliveMessages": "Blast alive messages", - "LabelEnableAutomaticPortMap": "Enable automatic port mapping", - "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.", - "LabelEmbedAlbumArtDidl": "Embed album art in Didl", - "LabelEasyPinCode": "Easy pin code:", - "LabelDynamicExternalId": "{0} Id:", - "LabelDropShadow": "Drop shadow:", - "LabelDropImageHere": "Drop image here, or click to browse.", - "LabelDownloadLanguages": "Download languages:", - "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. A value of one will preserve the original volume.", - "LabelDownMixAudioScale": "Audio boost when downmixing:", - "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in", - "LabelDisplayOrder": "Display order:", - "LabelDisplayName": "Display name:", - "LabelDateAddedBehaviorHelp": "If a metadata value is present it will always be used before either of these options.", - "LabelCustomDeviceDisplayName": "Display name:", - "LabelCustomCss": "Custom CSS:", - "LabelCustomCertificatePathHelp": "Path to a PKCS #12 file containing a certificate and private key to enable TLS support on a custom domain.", - "LabelCurrentPassword": "Current password:", - "LabelCriticRating": "Critic rating:", - "LabelCountry": "Country:", - "LabelContentType": "Content type:", - "LabelCommunityRating": "Community rating:", - "LabelCertificatePassword": "Certificate password:", - "LabelCancelled": "Cancelled", - "LabelCachePathHelp": "Specify a custom location for server cache files such as images. Leave blank to use the server default.", - "LabelCachePath": "Cache path:", - "LabelCache": "Cache:", - "LabelBurnSubtitles": "Burn subtitles:", - "LabelBlockContentWithTags": "Block items with tags:", - "LabelBirthYear": "Birth year:", - "LabelBirthDate": "Birth date:", - "LabelBindToLocalNetworkAddress": "Bind to local network address:", - "LabelAutomaticallyRefreshInternetMetadataEvery": "Automatically refresh metadata from the internet:", - "LabelAuthProvider": "Authentication Provider:", - "LabelAudioLanguagePreference": "Preferred audio language:", - "LabelAudioCodec": "Audio codec:", - "LabelAudioChannels": "Audio channels:", - "LabelAudioBitrate": "Audio bitrate:", - "LabelAudioBitDepth": "Audio bit depth:", - "LabelAudio": "Audio", - "LabelArtistsHelp": "Separate multiple using ;", - "LabelArtists": "Artists:", - "LabelAppName": "App name", - "LabelAllowedRemoteAddressesMode": "Remote IP address filter mode:", - "LabelAllowedRemoteAddresses": "Remote IP address filter:", - "LabelAllowServerAutoRestartHelp": "The server will only restart during idle periods when no users are active.", - "LabelAllowServerAutoRestart": "Allow the server to restart automatically to apply updates", - "LabelAllowHWTranscoding": "Allow hardware transcoding", - "LabelAll": "All", - "LabelAlbumArtists": "Album artists:", - "LabelAlbumArtPN": "Album art PN:", - "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.", - "LabelAlbumArtMaxHeightHelp": "Max resolution of album art exposed via upnp:albumArtURI.", - "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some devices require a specific value, regardless of the size of the image.", - "LabelAirsBeforeSeason": "Airs before season:", - "LabelAirsBeforeEpisode": "Airs before episode:", - "LabelAirsAfterSeason": "Airs after season:", - "LabelAirTime": "Air time:", - "LabelAirDays": "Air days:", - "LabelAccessEnd": "End time:", - "LabelAccessDay": "Day of week:", - "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", - "Kids": "Kids", - "Items": "Items", - "ItemCount": "{0} items", - "InstantMix": "Instant mix", - "Images": "Images", - "Identify": "Identify", - "Horizontal": "Horizontal", - "Home": "Home", - "HideWatchedContentFromLatestMedia": "Hide watched content from latest media", - "Hide": "Hide", - "Help": "Help", - "HeadersFolders": "Folders", - "HeaderXmlSettings": "XML Settings", - "HeaderXmlDocumentAttributes": "XML Document Attributes", - "HeaderXmlDocumentAttribute": "XML Document Attribute", - "HeaderVideoType": "Video Type", - "HeaderVideoQuality": "Video Quality", - "HeaderUsers": "Users", - "HeaderUser": "User", - "HeaderUploadImage": "Upload Image", - "HeaderUpcomingOnTV": "Upcoming On TV", - "HeaderTypeText": "Enter Text", - "HeaderTypeImageFetchers": "{0} Image Fetchers", - "HeaderTuners": "Tuners", - "HeaderTunerDevices": "Tuner Devices", - "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.", - "HeaderTranscodingProfile": "Transcoding Profile", - "HeaderTracks": "Tracks", - "HeaderThisUserIsCurrentlyDisabled": "This user is currently disabled", - "HeaderTaskTriggers": "Task Triggers", - "HeaderTags": "Tags", - "HeaderSystemDlnaProfiles": "System Profiles", - "HeaderSubtitleProfilesHelp": "Subtitle profiles describe the subtitle formats supported by the device.", - "HeaderSubtitleProfiles": "Subtitle Profiles", - "HeaderSubtitleProfile": "Subtitle Profile", - "Overview": "Overview", - "LabelLogs": "Logs:", - "Whitelist": "Whitelist", - "ServerNameIsRestarting": "Jellyfin Server - {0} is restarting.", - "OptionProtocolHls": "HTTP Live Streaming", - "OptionProfileVideoAudio": "Video Audio", - "OptionPosterCard": "Poster card", - "OptionPoster": "Poster", - "OptionPlayed": "Played", - "OneChannel": "One channel", - "MediaInfoChannels": "Channels", - "MediaInfoBitDepth": "Bit depth", - "LabelAlbum": "Album:", - "LabelProfileCodecs": "Codecs:", - "LabelPasswordRecoveryPinCode": "Pin code:", - "LabelPasswordResetProvider": "Password Reset Provider:", - "LabelPasswordConfirm": "Password (confirm):", - "LabelOriginalTitle": "Original title:", - "LabelOptionalNetworkPathHelp": "If this folder is shared on your network, supplying the network share path can allow Jellyfin apps on other devices to access media files directly. For example, {0} or {1}.", - "LabelNumberOfGuideDaysHelp": "Downloading more days worth of guide data provides the ability to schedule out further in advance and view more listings, but it will also take longer to download. Auto will choose based on the number of channels.", - "LabelNumberOfGuideDays": "Number of days of guide data to download:", - "LabelNumber": "Number:", - "LabelNotificationEnabled": "Enable this notification", - "SeriesDisplayOrderHelp": "Order episodes by air date, DVD order, or absolute numbering.", - "PleaseEnterNameOrId": "Please enter a name or an external ID.", - "OptionTvdbRating": "TVDB Rating", - "OptionDvd": "DVD", - "MessageDirectoryPickerLinuxInstruction": "For Linux on Arch Linux, CentOS, Debian, Fedora, openSUSE, or Ubuntu, you must grant the service user at least read access to your storage locations.", - "LabelCustomCertificatePath": "Custom SSL certificate path:", - "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.", - "LabelAppNameExample": "Example: Sickbeard, Sonarr", - "HttpsRequiresCert": "To enable secure connections, you will need to supply a trusted SSL certificate, such as Let's Encrypt. Please either supply a certificate, or disable secure connections.", - "Yesterday": "Yesterday", - "Yes": "Yes", - "XmlTvPathHelp": "A path to an XMLTV file. Jellyfin will read this file and periodically check it for updates. You are responsible for creating and updating the file.", - "WelcomeToProject": "Welcome to Jellyfin!", - "Wednesday": "Wednesday", - "Watched": "Watched", - "ViewPlaybackInfo": "View playback info", - "ViewAlbum": "View album", - "VideoRange": "Video range", - "SubtitleAppearanceSettingsAlsoPassedToCastDevices": "These settings also apply to any Chromecast playback started by this device.", - "Studios": "Studios", - "StopRecording": "Stop recording", - "Sports": "Sports", - "OptionProfilePhoto": "Photo", - "OptionPlainStorageFolders": "Display all folders as plain storage folders", - "OptionDisableUserHelp": "If disabled the server will not allow any connections from this user. Existing connections will be abruptly terminated.", - "OptionDateAdded": "Date Added", - "OptionDaily": "Daily", - "OptionContinuing": "Continuing", - "OptionCommunityRating": "Community Rating", - "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders.", - "LinksValue": "Links: {0}", - "LabelSelectVersionToInstall": "Select version to install:", - "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata.", - "OptionLikes": "Likes", - "OptionIsSD": "SD", - "OptionIsHD": "HD", - "OptionImdbRating": "IMDb Rating", - "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests", - "OptionHomeVideos": "Photos", - "OptionHlsSegmentedSubtitles": "HLS segmented subtitles", - "OptionHideUserFromLoginHelp": "Useful for private or hidden administrator accounts. The user will need to sign in manually by entering their username and password.", - "OptionHideUser": "Hide this user from login screens", - "OptionHasTrailer": "Trailer", - "OptionHasThemeVideo": "Theme Video", - "OptionHasThemeSong": "Theme Song", - "OptionHasSubtitles": "Subtitles", - "OptionHasSpecialFeatures": "Special Features", - "OptionFriday": "Friday", - "OptionExtractChapterImage": "Enable chapter image extraction", - "OptionExternallyDownloaded": "External download", - "OptionEquals": "Equals", - "OptionEnded": "Ended", - "OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.", - "OptionEnableM2tsMode": "Enable M2ts mode", - "OptionEnableExternalContentInSuggestions": "Enable external content in suggestions", - "OptionEnableAccessToAllLibraries": "Enable access to all libraries", - "OptionEnableAccessToAllChannels": "Enable access to all channels", - "OptionEnableAccessFromAllDevices": "Enable access from all devices", - "OptionEmbedSubtitles": "Embed within container", - "OptionDownloadThumbImage": "Thumb", - "OptionDownloadPrimaryImage": "Primary", - "OptionDownloadMenuImage": "Menu", - "OptionDownloadLogoImage": "Logo", - "OptionDownloadImagesInAdvanceHelp": "By default, most images are only downloaded when requested by a Jellyfin app. Enable this option to download all images in advance, as new media is imported. This may cause significantly longer library scans.", - "OptionDownloadImagesInAdvance": "Download images in advance", - "OptionDownloadDiscImage": "Disc", - "OptionDownloadBoxImage": "Box", - "OptionDownloadBannerImage": "Banner", - "OptionDownloadBackImage": "Back", - "OptionDownloadArtImage": "Art", - "OptionDisplayFolderView": "Display a folder view to show plain media folders", - "LabelMovieRecordingPath": "Movie recording path (optional):", - "LabelMoviePrefixHelp": "If a prefix is applied to movie titles, enter it here so the server can handle it properly.", - "LabelMessageTitle": "Message title:", - "LabelMessageText": "Message text:", - "LabelMaxStreamingBitrateHelp": "Specify a maximum bitrate when streaming.", - "LabelMaxStreamingBitrate": "Maximum streaming quality:", - "LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:", - "LabelMaxParentalRating": "Maximum allowed parental rating:", - "LabelFolder": "Folder:", - "LabelBaseUrl": "Base URL:", - "ViewArtist": "View artist", - "Up": "Up", - "SearchForCollectionInternetMetadata": "Search the internet for artwork and metadata", - "MediaInfoStreamTypeSubtitle": "Subtitle", - "MediaInfoSoftware": "Software", - "ValueOneSeries": "1 series", - "MediaInfoBitrate": "Bitrate", - "LabelVideo": "Video", - "LabelPrevious": "Previous", - "LabelPostProcessorArgumentsHelp": "Use {path} as the path to the recording file.", - "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart to extrathumbs field", - "LabelInternetQuality": "Internet quality:", - "LabelFileOrUrl": "File or URL:", - "LabelDateAdded": "Date added:", - "LabelDashboardTheme": "Server dashboard theme:", - "LabelCustomRating": "Custom rating:", - "LabelCollection": "Collection:", - "LabelChannels": "Channels:", - "LabelCertificatePasswordHelp": "If your certificate requires a password, please enter it here.", - "ValueOneMovie": "1 movie", - "ValueOneEpisode": "1 episode", - "ValueEpisodeCount": "{0} episodes", - "TabPassword": "Password", - "TabParentalControl": "Parental Control", - "SkipEpisodesAlreadyInMyLibraryHelp": "Episodes will be compared using season and episode numbers, when available.", - "RefreshQueued": "Refresh queued.", - "Play": "Play", - "PasswordResetProviderHelp": "Choose a Password Reset Provider to be used when this user requests a password reset", - "OptionTuesday": "Tuesday", - "OptionReleaseDate": "Release Date", - "OptionDisplayFolderViewHelp": "Display folders alongside your other media libraries. This can be useful if you'd like to have a plain folder view.", - "OptionDislikes": "Dislikes", - "OptionDisableUser": "Disable this user", - "OptionDescending": "Descending", - "OptionDateAddedImportTime": "Use date scanned into the library", - "OptionDateAddedFileTime": "Use file creation date", - "OptionCustomUsers": "Custom", - "OptionCriticRating": "Critic Rating", - "OptionCaptionInfoExSamsung": "CaptionInfoEx (Samsung)", - "OptionBluray": "Blu-ray", - "OptionBlockMusic": "Music", - "OptionBlockLiveTvChannels": "Live TV Channels", - "OptionBlockBooks": "Books", - "OptionAutomatic": "Auto", - "OptionAuto": "Auto", - "OptionAscending": "Ascending", - "OptionAdminUsers": "Administrators", - "NoSubtitleSearchResultsFound": "No results found.", - "News": "News", - "MusicVideo": "Music Video", - "MusicArtist": "Music Artist", - "Mobile": "Mobile", - "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", - "MessageUnableToConnectToServer": "We're unable to connect to the selected server right now. Please ensure it is running and try again.", - "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:", - "MessageSettingsSaved": "Settings saved.", - "MessageReenableUser": "See below to reenable", - "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item or the global default value.", - "MessageItemsAdded": "Items added.", - "MessageItemSaved": "Item saved.", - "MessageDirectoryPickerBSDInstruction": "For BSD, you may need to configure storage within your FreeNAS Jail in order to allow Jellyfin to access it.", - "MessageConfirmShutdown": "Are you sure you wish to shutdown the server?", - "LabelSaveLocalMetadata": "Save artwork into media folders", - "LabelPleaseRestart": "Changes will take effect after manually reloading the web client.", - "ValueSongCount": "{0} songs", - "Save": "Save", - "People": "People", - "OptionNameSort": "Name", - "OptionMonday": "Monday", - "MusicAlbum": "Music Album", - "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, and Albums. Click the + button to start creating collections.", - "ShowTitle": "Show title", - "HeaderStopRecording": "Stop Recording", - "HeaderStatus": "Status", - "HeaderStartNow": "Start Now", - "HeaderSpecialFeatures": "Special Features", - "HeaderSpecialEpisodeInfo": "Special Episode Info", - "HeaderSortOrder": "Sort Order", - "HeaderSortBy": "Sort By", - "HeaderShutdown": "Shutdown", - "HeaderSetupLibrary": "Setup your media libraries", - "HeaderSettings": "Settings", - "HeaderServerSettings": "Server Settings", - "HeaderSeriesStatus": "Series Status", - "HeaderSeriesOptions": "Series Options", - "HeaderSeries": "Series", - "HeaderSendMessage": "Send Message", - "HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.", - "HeaderSubtitleDownloads": "Subtitle Downloads", - "HeaderSelectTranscodingPath": "Select Transcoding Temporary Path", - "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.", - "HeaderSelectServerCachePath": "Select Server Cache Path", - "HeaderSelectServer": "Select Server", - "HeaderSelectPath": "Select Path", - "HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.", - "HeaderSelectMetadataPath": "Select Metadata Path", - "HeaderSelectCertificatePath": "Select Certificate Path", - "HeaderSecondsValue": "{0} Seconds", - "HeaderSeasons": "Seasons", - "HeaderSchedule": "Schedule", - "HeaderScenes": "Scenes", - "HeaderRunningTasks": "Running Tasks", - "HeaderRevisionHistory": "Revision History", - "HeaderRestart": "Restart", - "HeaderResponseProfile": "Response Profile", - "HeaderRemoveMediaLocation": "Remove Media Location", - "HeaderRemoveMediaFolder": "Remove Media Folder", - "HeaderRemoteControl": "Remote Control", - "HeaderRecordingPostProcessing": "Recording Post Processing", - "HeaderRecordingOptions": "Recording Options", - "HeaderRecentlyPlayed": "Recently Played", - "HeaderProfileServerSettingsHelp": "These values control how Jellyfin Server will present itself to the device.", - "HeaderProfileInformation": "Profile Information", - "HeaderProfile": "Profile", - "HeaderPreferredMetadataLanguage": "Preferred Metadata Language", - "HeaderPluginInstallation": "Plugin Installation", - "HeaderPleaseSignIn": "Please sign in", - "HeaderPlaybackError": "Playback Error", - "HeaderPlayback": "Media Playback", - "HeaderPlayOn": "Play On", - "HeaderPlayAll": "Play All", - "HeaderPinCodeReset": "Reset Pin Code", - "HeaderPhotoAlbums": "Photo Albums", - "HeaderPeople": "People", - "HeaderHome": "Home", - "HeaderFavoritePeople": "Favourite People", - "FetchingData": "Fetching additional data", - "ButtonAddImage": "Add Image", - "OptionRandom": "Random", - "SelectAdminUsername": "Please select a username for the admin account.", - "ButtonSplit": "Split", - "HeaderNavigation": "Navigation", - "OptionForceRemoteSourceTranscoding": "Force transcoding of remote media sources (like LiveTV)", - "MessageConfirmAppExit": "Do you want to exit?", - "LabelVideoResolution": "Video resolution:", - "LabelStreamType": "Stream type:", - "LabelPlayerDimensions": "Player dimensions:", - "LabelDroppedFrames": "Dropped frames:", - "LabelCorruptedFrames": "Corrupted frames:", - "CopyStreamURLError": "There was an error copying the URL.", - "NoCreatedLibraries": "Seems like you haven't created any libraries yet. {0}Would you like to create one now?{1}", - "AskAdminToCreateLibrary": "Ask an administrator to create a library.", - "PlaybackErrorNoCompatibleStream": "This client isn't compatible with the media and the server isn't sending a compatible media format.", - "AllowFfmpegThrottlingHelp": "When a transcode or remux gets far enough ahead from the current playback position, pause the process so it will consume less resources. This is most useful when watching without seeking often. Turn this off if you experience playback issues.", - "AllowFfmpegThrottling": "Throttle Transcodes", - "OnApplicationStartup": "On application startup", - "EveryXHours": "Every {0} hours", - "EveryHour": "Every hour", - "EveryXMinutes": "Every {0} minutes", - "OnWakeFromSleep": "On wake from sleep", - "WeeklyAt": "{0}s at {1}", - "DailyAt": "Daily at {0}", - "LastSeen": "Last seen {0}", - "PersonRole": "as {0}", - "ListPaging": "{0}-{1} of {2}", - "WriteAccessRequired": "Jellyfin Server requires write access to this folder. Please ensure write access and try again.", - "PathNotFound": "The path could not be found. Please ensure the path is valid and try again.", - "YadifBob": "YADIF Bob", - "Yadif": "YADIF", - "Track": "Track", - "Season": "Season", - "ReleaseGroup": "Release Group", - "PreferEmbeddedEpisodeInfosOverFileNames": "Prefer embedded episode information over filenames", - "PreferEmbeddedEpisodeInfosOverFileNamesHelp": "This uses the episode information from the embedded metadata if available.", - "Person": "Person", - "OtherArtist": "Other Artist", - "Movie": "Movie", - "LabelLibraryPageSizeHelp": "Sets the amount of items to show on a library page. Set to 0 in order to disable paging.", - "LabelLibraryPageSize": "Library page size:", - "LabelDeinterlaceMethod": "Deinterlacing method:", - "Episode": "Episode", - "DeinterlaceMethodHelp": "Select the deinterlacing method to use when transcoding interlaced content.", - "ClientSettings": "Client Settings", - "BoxSet": "Box Set", - "Artist": "Artist", - "AlbumArtist": "Album Artist", - "Album": "Album", - "UnsupportedPlayback": "Jellyfin cannot decrypt content protected by DRM but all content will be attempted regardless, including protected titles. Some files may appear completely black due to encryption or other unsupported features, such as interactive titles.", - "MessageUnauthorizedUser": "You are not authorized to access the server at this time. Please contact your server administrator for more information.", - "ButtonTogglePlaylist": "Playlist", - "ButtonToggleContextMenu": "More", - "HeaderDVR": "DVR", - "ApiKeysCaption": "List of the currently enabled API keys", - "ButtonCast": "Cast", - "ButtonSyncPlay": "SyncPlay", - "EnableBlurhashHelp": "Images that are still being loaded will be displayed with a blurred placeholder", - "EnableBlurhash": "Enable blurred placeholders for images", - "TabDVR": "DVR", - "TabRepositories": "Repositories", - "SyncPlayAccessHelp": "Select the level of access this user has to the SyncPlay feature. SyncPlay enables to sync playback with other devices.", - "ShowMore": "Show more", - "ShowLess": "Show less", - "SaveChanges": "Save changes", - "MessageSyncPlayErrorMedia": "Failed to enable SyncPlay! Media error.", - "MessageSyncPlayErrorMissingSession": "Failed to enable SyncPlay! Missing session.", - "MessageSyncPlayErrorNoActivePlayer": "No active player found. SyncPlay has been disabled.", - "MessageSyncPlayErrorAccessingGroups": "An error occurred while accessing groups list.", - "MessageSyncPlayLibraryAccessDenied": "Access to this content is restricted.", - "MessageSyncPlayJoinGroupDenied": "Permission required to use SyncPlay.", - "MessageSyncPlayCreateGroupDenied": "Permission required to create a group.", - "MessageSyncPlayGroupDoesNotExist": "Failed to join group because it does not exist.", - "MessageSyncPlayPlaybackPermissionRequired": "Playback permission required.", - "MessageSyncPlayNoGroupsAvailable": "No groups available. Start playing something first.", - "MessageSyncPlayGroupWait": "{0} is buffering...", - "MessageSyncPlayUserLeft": "{0} has left the group.", - "MessageSyncPlayUserJoined": "{0} has joined the group.", - "MessageSyncPlayDisabled": "SyncPlay disabled.", - "MessageSyncPlayEnabled": "SyncPlay enabled.", - "MessageNoGenresAvailable": "Enable some metadata providers to pull genres from the internet.", - "MessageAddRepository": "If you wish to add a repository, click the button next to the header and fill out the requested information.", - "LabelRepositoryNameHelp": "A custom name to distinguish this repository from any others added to your server.", - "LabelRepositoryName": "Repository Name", - "LabelRepositoryUrlHelp": "The location of the repository manifest you want to include.", - "LabelRepositoryUrl": "Repository URL", - "HeaderNewRepository": "New Repository", - "MessageNoRepositories": "No repositories.", - "LabelSyncPlayAccess": "SyncPlay access", - "LabelSyncPlayAccessNone": "Disabled for this user", - "LabelSyncPlayAccessJoinGroups": "Allow user to join groups", - "LabelSyncPlayAccessCreateAndJoinGroups": "Allow user to create and join groups", - "LabelSyncPlayLeaveGroupDescription": "Disable SyncPlay", - "LabelSyncPlayLeaveGroup": "Leave group", - "LabelSyncPlayNewGroupDescription": "Create a new group", - "LabelSyncPlayNewGroup": "New group", - "LabelSyncPlaySyncMethod": "Sync method:", - "LabelSyncPlayPlaybackDiff": "Playback time difference:", - "MillisecondsUnit": "ms", - "LabelSyncPlayTimeOffset": "Time offset with the server:", - "LabelRequireHttpsHelp": "If checked, the server will automatically redirect all requests over HTTP to HTTPS. This has no effect if the server is not listening on HTTPS.", - "LabelRequireHttps": "Require HTTPS", - "LabelNightly": "Nightly", - "LabelStable": "Stable", - "LabelChromecastVersion": "Chromecast Version", - "LabelEnableHttpsHelp": "Enables the server to listen on the configured HTTPS port. A valid certificate must also be configured in order for this to take effect.", - "LabelEnableHttps": "Enable HTTPS", - "HeaderSyncPlayEnabled": "SyncPlay enabled", - "HeaderSyncPlaySelectGroup": "Join a group", - "HeaderServerAddressSettings": "Server Address Settings", - "HeaderRemoteAccessSettings": "Remote Access Settings", - "HeaderHttpsSettings": "HTTPS Settings", - "EnableDetailsBannerHelp": "Display a banner image at the top of the item details page.", - "EnableDetailsBanner": "Details Banner", - "EnableDecodingColorDepth10Vp9": "Enable 10-Bit hardware decoding for VP9", - "EnableDecodingColorDepth10Hevc": "Enable 10-Bit hardware decoding for HEVC", - "ViewAlbumArtist": "View album artist", - "ClearQueue": "Clear queue", - "StopPlayback": "Stop playback", - "ButtonPlayer": "Player", - "Writers": "Writers" + "AdditionalNotificationServices": "Browse the plugin catalogue to install additional notification services.", + "MessageBrowsePluginCatalog": "Browse our plugin catalogue to view available plugins.", + "CinemaModeConfigurationHelp": "Cinema mode brings the theatre experience straight to your living room with the ability to play trailers and custom intros before the main feature.", + "ColorPrimaries": "Colour primaries", + "ColorSpace": "Colour space", + "ColorTransfer": "Colour transfer", + "DefaultMetadataLangaugeDescription": "These are your defaults and can be customized on a per-library basis.", + "EnableColorCodedBackgrounds": "Colour coded backgrounds", + "Favorite": "Favourite", + "Favorites": "Favourites", + "HDPrograms": "HD programs", + "HeaderBlockItemsWithNoRating": "Block items with no or unrecognized rating information:", + "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.", + "ImportFavoriteChannelsHelp": "If enabled, only channels that are marked as favourite on the tuner device will be imported.", + "LabelDateAddedBehavior": "Date added behaviour for new content:", + "LabelImportOnlyFavoriteChannels": "Restrict to channels marked as favourite", + "LabelKodiMetadataUserHelp": "Save watch data to NFO files for other applications to utilize.", + "LabelTextBackgroundColor": "Text background color:", + "LabelTextColor": "Text color:", + "NewCollectionHelp": "Collections allow you to create personalized groupings of movies and other library content.", + "NoNewDevicesFound": "No new devices found. To add a new tuner, close this dialogueand enter the device information manually.", + "OptionEnableExternalContentInSuggestionsHelp": "Allow internet trailers and live TV programs to be included within suggested content.", + "OptionIgnoreTranscodeByteRangeRequestsHelp": "These requests will be honored but will ignore the byte range header.", + "PlaceFavoriteChannelsAtBeginning": "Place favourite channels at the beginning", + "Programs": "Programs", + "TabCatalog": "Catalogue", + "XmlTvKidsCategoriesHelp": "Programs with these categories will be displayed as programs for children. Separate multiple with '|'.", + "XmlTvMovieCategoriesHelp": "Programs with these categories will be displayed as movies. Separate multiple with '|'.", + "XmlTvNewsCategoriesHelp": "Programs with these categories will be displayed as news programs. Separate multiple with '|'.", + "XmlTvSportsCategoriesHelp": "Programs with these categories will be displayed as sports programs. Separate multiple with '|'.", + "Albums": "Albums", + "Artists": "Artists", + "Books": "Books", + "Channels": "Channels", + "Collections": "Collections", + "Folders": "Folders", + "Genres": "Genres", + "HeaderAlbumArtists": "Album Artists", + "HeaderContinueWatching": "Continue Watching", + "Movies": "Movies", + "Photos": "Photos", + "Playlists": "Playlists", + "Shows": "Shows", + "Songs": "Songs", + "Sync": "Sync", + "ValueSpecialEpisodeName": "Special - {0}", + "Absolute": "Absolute", + "AccessRestrictedTryAgainLater": "Access is currently restricted. Please try again later.", + "Actor": "Actor", + "Add": "Add", + "AddToCollection": "Add to collection", + "AddToPlayQueue": "Add to play queue", + "AddToPlaylist": "Add to playlist", + "AddedOnValue": "Added {0}", + "AirDate": "Air date", + "Aired": "Aired", + "Alerts": "Alerts", + "All": "All", + "AllChannels": "All channels", + "AllComplexFormats": "All Complex Formats (ASS, SSA, VOBSUB, PGS, SUB, IDX, …)", + "AllEpisodes": "All episodes", + "AllLanguages": "All languages", + "AllLibraries": "All libraries", + "AllowHWTranscodingHelp": "Allow the tuner to transcode streams on the fly. This may help reduce transcoding required by the server.", + "AllowMediaConversion": "Allow media conversion", + "AllowMediaConversionHelp": "Grant or deny access to the convert media feature.", + "AllowOnTheFlySubtitleExtraction": "Allow subtitle extraction on the fly", + "AllowOnTheFlySubtitleExtractionHelp": "Embedded subtitles can be extracted from videos and delivered to clients in plain text, in order to help prevent video transcoding. On some systems this can take a long time and cause video playback to stall during the extraction process. Disable this to have embedded subtitles burned in with video transcoding when they are not natively supported by the client device.", + "AllowRemoteAccess": "Allow remote connections to this server.", + "AllowRemoteAccessHelp": "If unchecked, all remote connections will be blocked.", + "AllowedRemoteAddressesHelp": "Comma separated list of IP addresses or IP/netmask entries for networks that will be allowed to connect remotely. If left blank, all remote addresses will be allowed.", + "AlwaysPlaySubtitles": "Always Play", + "AlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.", + "AnyLanguage": "Any Language", + "Anytime": "Anytime", + "AroundTime": "Around", + "Art": "Art", + "AsManyAsPossible": "As many as possible", + "Ascending": "Ascending", + "AspectRatio": "Aspect Ratio", + "Audio": "Audio", + "AuthProviderHelp": "Select an authentication provider to be used to authenticate this user's password.", + "Auto": "Auto", + "Backdrop": "Backdrop", + "Backdrops": "Backdrops", + "Banner": "Banner", + "BirthDateValue": "Born: {0}", + "BirthLocation": "Birth location", + "BirthPlaceValue": "Birth place: {0}", + "Blacklist": "Blacklist", + "BookLibraryHelp": "Audio and text books are supported. Review the {0} book naming guide {1}.", + "Box": "Box", + "BoxRear": "Box (rear)", + "Browse": "Browse", + "BurnSubtitlesHelp": "Determines if the server should burn in subtitles when transcoding videos. Avoiding this will greatly improve performance. Select Auto to burn image based formats (VOBSUB, PGS, SUB, IDX, …) and certain ASS or SSA subtitles.", + "ButtonAddMediaLibrary": "Add Media Library", + "ButtonAddScheduledTaskTrigger": "Add Trigger", + "ButtonAddServer": "Add Server", + "ButtonAddUser": "Add User", + "ButtonArrowLeft": "Left", + "ButtonArrowRight": "Right", + "ButtonAudioTracks": "Audio Tracks", + "ButtonBack": "Back", + "ButtonCancel": "Cancel", + "ButtonChangeServer": "Change Server", + "ButtonEditOtherUserPreferences": "Edit this user's profile, image and personal preferences.", + "ButtonForgotPassword": "Forgot Password", + "ButtonFullscreen": "Fullscreen", + "ButtonGotIt": "Got It", + "ButtonInfo": "Info", + "ButtonLibraryAccess": "Library access", + "ButtonManualLogin": "Manual Login", + "ButtonMore": "More", + "ButtonNetwork": "Network", + "ButtonNextTrack": "Next track", + "ButtonOk": "OK", + "ButtonOpen": "Open", + "ButtonParentalControl": "Parental control", + "ButtonPause": "Pause", + "ButtonPreviousTrack": "Previous track", + "ButtonQuickStartGuide": "Quick Start Guide", + "ButtonRefreshGuideData": "Refresh Guide Data", + "ButtonRemove": "Remove", + "ButtonRename": "Rename", + "ButtonResetEasyPassword": "Reset easy pin code", + "ButtonResume": "Resume", + "ButtonRevoke": "Revoke", + "ButtonScanAllLibraries": "Scan All Libraries", + "ButtonSelectDirectory": "Select Directory", + "ButtonSelectView": "Select view", + "ButtonSend": "Send", + "ButtonShutdown": "Shutdown", + "ButtonSignIn": "Sign In", + "ButtonSignOut": "Sign Out", + "ButtonStart": "Start", + "ButtonStop": "Stop", + "ButtonSubmit": "Submit", + "ButtonTrailer": "Trailer", + "ButtonUninstall": "Uninstall", + "ButtonWebsite": "Website", + "CancelRecording": "Cancel recording", + "CancelSeries": "Cancel series", + "Categories": "Categories", + "ChangingMetadataImageSettingsNewContent": "Changes to metadata or artwork downloading settings will only apply to new content added to your library. To apply the changes to existing titles, you'll need to refresh their metadata manually.", + "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.", + "ChannelNameOnly": "Channel {0} only", + "ChannelNumber": "Channel number", + "CommunityRating": "Community rating", + "Composer": "Composer", + "ConfigureDateAdded": "Configure how date added is determined in the dashboard under the library settings", + "ConfirmDeleteImage": "Delete image?", + "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?", + "ConfirmDeleteItems": "Deleting these items will delete them from both the file system and your media library. Are you sure you wish to continue?", + "ConfirmDeletion": "Confirm Deletion", + "ConfirmEndPlayerSession": "Would you like to shutdown Jellyfin on {0}?", + "Connect": "Connect", + "ContinueWatching": "Continue watching", + "Continuing": "Continuing", + "CriticRating": "Critic rating", + "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.", + "DateAdded": "Date added", + "DatePlayed": "Date played", + "DeathDateValue": "Died: {0}", + "Default": "Default", + "ErrorDefault": "There was an error processing the request. Please try again later.", + "DefaultSubtitlesHelp": "Subtitles are loaded based on the default and forced flags in the embedded metadata. Language preferences are considered when multiple options are available.", + "Delete": "Delete", + "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", + "DeleteImage": "Delete Image", + "DeleteImageConfirmation": "Are you sure you wish to delete this image?", + "DeleteMedia": "Delete media", + "DeleteUser": "Delete User", + "DeleteUserConfirmation": "Are you sure you wish to delete this user?", + "Depressed": "Depressed", + "Descending": "Descending", + "Desktop": "Desktop", + "DetectingDevices": "Detecting devices", + "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", + "DirectPlaying": "Direct playing", + "DirectStreamHelp1": "The media is compatible with the device regarding resolution and media type (H.264, AC3, etc), but in an incompatible file container (mkv, avi, wmv, etc). The video will be re-packaged on the fly before being sent to the device.", + "DirectStreamHelp2": "Direct stream uses very little processing power with a minimal loss in video quality.", + "DirectStreaming": "Direct streaming", + "Director": "Director", + "Directors": "Directors", + "Disc": "Disc", + "Disconnect": "Disconnect", + "Display": "Display", + "DisplayInMyMedia": "Display on home screen", + "DisplayInOtherHomeScreenSections": "Display in home screen sections such as latest media and continue watching", + "DisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", + "DisplayMissingEpisodesWithinSeasonsHelp": "This must also be enabled for TV libraries in the server configuration.", + "DisplayModeHelp": "Select the layout style you want for the interface.", + "DoNotRecord": "Do not record", + "Down": "Down", + "Download": "Download", + "DownloadsValue": "{0} downloads", + "DrmChannelsNotImported": "Channels with DRM will not be imported.", + "DropShadow": "Drop Shadow", + "EasyPasswordHelp": "Your easy pin code is used for offline access on supported clients and can also be used for easy in-network sign in.", + "Edit": "Edit", + "EditImages": "Edit images", + "EditMetadata": "Edit metadata", + "EditSubtitles": "Edit subtitles", + "EnableBackdropsHelp": "Display backdrops in the background of some pages while browsing the library.", + "EnableCinemaMode": "Cinema mode", + "EnableDisplayMirroring": "Display mirroring", + "EnableExternalVideoPlayers": "External video players", + "EnableExternalVideoPlayersHelp": "An external player menu will be shown when starting video playback.", + "EnableHardwareEncoding": "Enable hardware encoding", + "EnableNextVideoInfoOverlay": "Show next video info during playback", + "EnableNextVideoInfoOverlayHelp": "At the end of a video, display info about the next video coming up in the current playlist.", + "EnablePhotos": "Display photos", + "EnablePhotosHelp": "Images will be detected and displayed alongside other media files.", + "EnableStreamLooping": "Auto-loop live streams", + "EnableStreamLoopingHelp": "Enable this if live streams only contain a few seconds of data and need to be continuously requested. Enabling this when not needed may cause problems.", + "EnableThemeSongsHelp": "Play theme songs in the background while browsing the library.", + "EnableThemeVideosHelp": "Play theme videos in the background while browsing the library.", + "Ended": "Ended", + "EndsAtValue": "Ends at {0}", + "Episodes": "Episodes", + "ErrorAddingListingsToSchedulesDirect": "There was an error adding the lineup to your Schedules Direct account. Schedules Direct only allows a limited number of lineups per account. You may need to log into the Schedules Direct website and remove others listings from your account before proceeding.", + "ErrorAddingMediaPathToVirtualFolder": "There was an error adding the media path. Please ensure the path is valid and Jellyfin has access to that location.", + "ErrorAddingTunerDevice": "There was an error adding the tuner device. Please ensure it is accessible and try again.", + "ErrorAddingXmlTvFile": "There was an error accessing the XMLTV file. Please ensure the file exists and try again.", + "ErrorDeletingItem": "There was an error deleting the item from the server. Please check that Jellyfin has write access to the media folder and try again.", + "ErrorGettingTvLineups": "There was an error downloading TV lineups. Please ensure your information is correct and try again.", + "ErrorStartHourGreaterThanEnd": "End time must be greater than the start time.", + "ErrorPleaseSelectLineup": "Please select a lineup and try again. If no lineups are available, then please check that your username, password, and postal code is correct.", + "ErrorSavingTvProvider": "There was an error saving the TV provider. Please ensure it is accessible and try again.", + "EveryNDays": "Every {0} days", + "ExitFullscreen": "Exit full screen", + "ExtraLarge": "Extra Large", + "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, resource intensive, and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "Extras": "Extras", + "FFmpegSavePathNotFound": "We're unable to locate FFmpeg using the path you've entered. FFprobe is also required and must exist in the same folder. These components are normally bundled together in the same download. Please check the path and try again.", + "FastForward": "Fast-forward", + "Features": "Features", + "File": "File", + "FileNotFound": "File not found.", + "FileReadCancelled": "The file read has been cancelled.", + "FileReadError": "An error occurred while reading the file.", + "Filters": "Filters", + "FormatValue": "Format: {0}", + "Friday": "Friday", + "Fullscreen": "Full screen", + "General": "General", + "Genre": "Genre", + "GroupBySeries": "Group by series", + "GroupVersions": "Group versions", + "GuestStar": "Guest star", + "Guide": "Guide", + "GuideProviderLogin": "Login", + "GuideProviderSelectListings": "Select Listings", + "H264CrfHelp": "The Constant Rate Factor (CRF) is the default quality setting for the x264 encoder. You can set the values between 0 and 51, where lower values would result in better quality (at the expense of higher file sizes). Sane values are between 18 and 28. The default for x264 is 23, so you can use this as a starting point.", + "EncoderPresetHelp": "Choose a faster value to improve performance, or a slower value to improve quality.", + "HardwareAccelerationWarning": "Enabling hardware acceleration may cause instability in some environments. Ensure that your operating system and video drivers are fully up to date. If you have difficulty playing video after enabling this, you'll need to change the setting back to None.", + "HeaderAccessSchedule": "Access Schedule", + "HeaderAccessScheduleHelp": "Create an access schedule to limit access to certain hours.", + "HeaderActiveDevices": "Active Devices", + "HeaderActiveRecordings": "Active Recordings", + "HeaderActivity": "Activity", + "HeaderAddToCollection": "Add to Collection", + "HeaderAddToPlaylist": "Add to Playlist", + "HeaderAddUpdateImage": "Add/Update Image", + "HeaderAdditionalParts": "Additional Parts", + "HeaderAdmin": "Admin", + "HeaderAlert": "Alert", + "HeaderAllowMediaDeletionFrom": "Allow Media Deletion From", + "HeaderApiKey": "API Key", + "HeaderApiKeys": "API Keys", + "HeaderApiKeysHelp": "External applications are required to have an API key in order to communicate with the server. Keys are issued by logging in with a normal user account or manually granting the application a key.", + "HeaderApp": "App", + "HeaderAppearsOn": "Appears On", + "HeaderAudioBooks": "Audio Books", + "HeaderAudioSettings": "Audio Settings", + "HeaderBranding": "Branding", + "HeaderCancelRecording": "Cancel Recording", + "HeaderCancelSeries": "Cancel Series", + "HeaderCastAndCrew": "Cast & Crew", + "HeaderChannelAccess": "Channel Access", + "HeaderChapterImages": "Chapter Images", + "HeaderCodecProfile": "Codec Profile", + "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.", + "HeaderConfigureRemoteAccess": "Configure Remote Access", + "HeaderConfirmPluginInstallation": "Confirm Plugin Installation", + "HeaderConfirmProfileDeletion": "Confirm Profile Deletion", + "HeaderConfirmRevokeApiKey": "Revoke API Key", + "HeaderConnectToServer": "Connect to Server", + "HeaderConnectionFailure": "Connection Failure", + "HeaderContainerProfile": "Container Profile", + "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.", + "HeaderContinueListening": "Continue Listening", + "HeaderCustomDlnaProfiles": "Custom Profiles", + "HeaderDateIssued": "Date Issued", + "HeaderDefaultRecordingSettings": "Default Recording Settings", + "HeaderDeleteDevice": "Delete Device", + "HeaderDeleteItem": "Delete Item", + "HeaderDeleteItems": "Delete Items", + "HeaderDeleteProvider": "Delete Provider", + "HeaderDeleteTaskTrigger": "Delete Task Trigger", + "HeaderDetectMyDevices": "Detect My Devices", + "HeaderDeveloperInfo": "Developer Info", + "HeaderDeviceAccess": "Device Access", + "HeaderDevices": "Devices", + "HeaderDirectPlayProfile": "Direct Play Profile", + "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.", + "HeaderDownloadSync": "Download & Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "HeaderEditImages": "Edit Images", + "HeaderEnabledFields": "Enabled Fields", + "HeaderEnabledFieldsHelp": "Uncheck a field to lock it and prevent its data from being changed.", + "HeaderError": "Error", + "HeaderExternalIds": "External IDs:", + "HeaderFeatureAccess": "Feature Access", + "HeaderFetchImages": "Fetch Images:", + "HeaderFetcherSettings": "Fetcher Settings", + "HeaderForKids": "For Kids", + "HeaderFrequentlyPlayed": "Frequently Played", + "HeaderGuideProviders": "TV Guide Data Providers", + "HeaderHttpHeaders": "HTTP Headers", + "HeaderIdentification": "Identification", + "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.", + "HeaderIdentificationHeader": "Identification Header", + "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.", + "HeaderImageOptions": "Image Options", + "HeaderImageSettings": "Image Settings", + "HeaderInstall": "Install", + "HeaderInstantMix": "Instant Mix", + "HeaderKeepRecording": "Keep Recording", + "HeaderKeepSeries": "Keep Series", + "HeaderKodiMetadataHelp": "To enable or disable NFO metadata, edit a library and locate the metadata savers section.", + "HeaderLatestEpisodes": "Latest Episodes", + "HeaderLatestMedia": "Latest Media", + "HeaderLatestMovies": "Latest Movies", + "HeaderLatestMusic": "Latest Music", + "HeaderLatestRecordings": "Latest Recordings", + "HeaderLibraries": "Libraries", + "HeaderLibraryAccess": "Library Access", + "HeaderLibraryFolders": "Library Folders", + "HeaderLibraryOrder": "Library Order", + "HeaderLibrarySettings": "Library Settings", + "HeaderLiveTvTunerSetup": "Live TV Tuner Setup", + "HeaderLoginFailure": "Login Failure", + "HeaderMedia": "Media", + "HeaderMediaFolders": "Media Folders", + "HeaderMetadataSettings": "Metadata Settings", + "HeaderMoreLikeThis": "More Like This", + "HeaderMusicQuality": "Music Quality", + "HeaderMyDevice": "My Device", + "HeaderMyMedia": "My Media", + "HeaderMyMediaSmall": "My Media (small)", + "HeaderNewApiKey": "New API Key", + "HeaderNewDevices": "New Devices", + "HeaderNextEpisodePlayingInValue": "Next Episode Playing in {0}", + "HeaderNextVideoPlayingInValue": "Next Video Playing in {0}", + "HeaderOnNow": "On Now", + "HeaderOtherItems": "Other Items", + "HeaderParentalRatings": "Parental Ratings", + "HeaderPassword": "Password", + "HeaderPasswordReset": "Password Reset", + "HeaderPaths": "Paths", + "CopyStreamURL": "Copy Stream URL", + "CopyStreamURLSuccess": "URL copied successfully.", + "XmlDocumentAttributeListHelp": "These attributes are applied to the root element of every XML response.", + "Writer": "Writer", + "WizardCompleted": "That's all we need for now. Jellyfin has begun collecting information about your media library. Check out some of our apps, and then click Finish to view the Dashboard.", + "Vertical": "Vertical", + "ValueVideoCodec": "Video Codec: {0}", + "ValueTimeLimitSingleHour": "Time limit: 1 hour", + "ValueTimeLimitMultiHour": "Time limit: {0} hours", + "ValueSeriesCount": "{0} series", + "ValueSeconds": "{0} seconds", + "ValueOneSong": "1 song", + "ValueOneMusicVideo": "1 music video", + "ValueOneAlbum": "1 album", + "ValueMusicVideoCount": "{0} music videos", + "ValueMovieCount": "{0} movies", + "ValueMinutes": "{0} min", + "ValueDiscNumber": "Disc {0}", + "ValueContainer": "Container: {0}", + "ValueConditions": "Conditions: {0}", + "ValueCodec": "Codec: {0}", + "ValueAudioCodec": "Audio Codec: {0}", + "ValueAlbumCount": "{0} albums", + "UserProfilesIntro": "Jellyfin includes support for user profiles with granular display settings, play state, and parental controls.", + "UserAgentHelp": "Supply a custom user-agent HTTP header.", + "Upload": "Upload", + "Unrated": "Unrated", + "Unplayed": "Unplayed", + "Unmute": "Unmute", + "HeaderUninstallPlugin": "Uninstall Plugin", + "Trailers": "Trailers", + "TrackCount": "{0} tracks", + "TitlePlayback": "Playback", + "TitleHostingSettings": "Hosting Settings", + "TitleHardwareAcceleration": "Hardware Acceleration", + "Thursday": "Thursday", + "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process. To begin, please select your preferred language.", + "TheseSettingsAffectSubtitlesOnThisDevice": "These settings affect subtitles on this device", + "TabServer": "Server", + "TabScheduledTasks": "Scheduled Tasks", + "TabResponses": "Responses", + "TabOther": "Other", + "TabNotifications": "Notifications", + "TabNetworks": "Networks", + "TabMyPlugins": "My Plugins", + "TabMusic": "Music", + "TabLogs": "Logs", + "TabDirectPlay": "Direct Play", + "TabAdvanced": "Advanced", + "TabAccess": "Access", + "TV": "TV", + "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.", + "Sunday": "Sunday", + "Suggestions": "Suggestions", + "Subtitles": "Subtitles", + "SubtitleOffset": "Subtitle Offset", + "SubtitleDownloadersHelp": "Enable and rank your preferred subtitle downloaders in order of priority.", + "SubtitleAppearanceSettingsDisclaimer": "These settings will not apply to graphical subtitles (PGS, DVD, etc) or ASS/SSA subtitles that embed their own styles.", + "SortName": "Sort name", + "SortChannelsBy": "Sort channels by:", + "SortByValue": "Sort by {0}", + "SmartSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.", + "Smart": "Smart", + "SimultaneousConnectionLimitHelp": "The maximum number of allowed simultaneous streams. Enter 0 for no limit.", + "Shuffle": "Shuffle", + "New": "New", + "Filter": "Filter", + "ShowYear": "Show year", + "ShowIndicatorsFor": "Show indicators for:", + "ShowAdvancedSettings": "Show advanced settings", + "Share": "Share", + "SettingsWarning": "Changing these values may cause instability or connectivity failures. If you experience any problems, we recommend changing them back to default.", + "SettingsSaved": "Settings saved.", + "Settings": "Settings", + "ServerUpdateNeeded": "This server needs to be updated. To download the latest version, please visit {0}", + "ServerRestartNeededAfterPluginInstall": "Jellyfin will need to be restarted after installing a plugin.", + "ServerNameIsShuttingDown": "The server at {0} is shutting down.", + "SeriesYearToPresent": "{0} - Present", + "SeriesSettings": "Series settings", + "SeriesRecordingScheduled": "Series recording scheduled.", + "SeriesCancelled": "Series cancelled.", + "SendMessage": "Send message", + "SearchResults": "Search Results", + "SearchForSubtitles": "Search for Subtitles", + "SearchForMissingMetadata": "Search for missing metadata", + "Search": "Search", + "Screenshots": "Screenshots", + "Screenshot": "Screenshot", + "Schedule": "Schedule", + "ScanLibrary": "Scan library", + "ScanForNewAndUpdatedFiles": "Scan for new and updated files", + "SaveSubtitlesIntoMediaFoldersHelp": "Storing subtitles next to video files will allow them to be more easily managed.", + "SaveSubtitlesIntoMediaFolders": "Save subtitles into media folders", + "Saturday": "Saturday", + "Runtime": "Runtime", + "Rewind": "Rewind", + "ResumeAt": "Resume from {0}", + "ReplaceExistingImages": "Replace existing images", + "ReplaceAllMetadata": "Replace all metadata", + "RepeatOne": "Repeat one", + "RepeatMode": "Repeat Mode", + "RepeatEpisodes": "Repeat episodes", + "RepeatAll": "Repeat all", + "Repeat": "Repeat", + "RemoveFromPlaylist": "Remove from playlist", + "RemoveFromCollection": "Remove from collection", + "RememberMe": "Remember Me", + "ReleaseDate": "Release date", + "RefreshMetadata": "Refresh metadata", + "RefreshDialogHelp": "Metadata is refreshed based on settings and internet services that are enabled in the dashboard.", + "Refresh": "Refresh", + "Recordings": "Recordings", + "RecordingScheduled": "Recording scheduled.", + "MessageChangeRecordingPath": "Changing your recording folder will not migrate existing recordings from the old location to the new. You'll need to move them manually if desired.", + "RecordingCancelled": "Recording cancelled.", + "RecordSeries": "Record series", + "Record": "Record", + "RecommendationStarring": "Starring {0}", + "RecommendationDirectedBy": "Directed by {0}", + "RecommendationBecauseYouWatched": "Because you watched {0}", + "Rate": "Rate", + "Raised": "Raised", + "Quality": "Quality", + "Producer": "Producer", + "Primary": "Primary", + "Previous": "Previous", + "Premieres": "Premieres", + "Premiere": "Premiere", + "PreferEmbeddedTitlesOverFileNamesHelp": "This determines the default display title when no internet metadata or local metadata is available.", + "PreferEmbeddedTitlesOverFileNames": "Prefer embedded titles over filenames", + "MessagePluginInstalled": "The plugin has been successfully installed. The server will need to be restarted for changes to take effect.", + "PleaseSelectTwoItems": "Please select at least two items.", + "PleaseRestartServerName": "Please restart Jellyfin on {0}.", + "PleaseConfirmPluginInstallation": "Please click OK to confirm you've read the above and wish to proceed with the plugin installation.", + "PleaseAddAtLeastOneFolder": "Please add at least one folder to this library by clicking the Add button.", + "Played": "Played", + "PlayNextEpisodeAutomatically": "Play next episode automatically", + "PlayNext": "Play next", + "PlayFromBeginning": "Play from beginning", + "PlayCount": "Play count", + "PlaybackData": "Playback Data", + "PlayAllFromHere": "Play all from here", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "PinCodeResetComplete": "The pin code has been reset.", + "PictureInPicture": "Picture in picture", + "PerfectMatch": "Perfect match", + "PasswordSaved": "Password saved.", + "PasswordResetConfirmation": "Are you sure you wish to reset the password?", + "PasswordResetComplete": "The password has been reset.", + "PasswordMatchError": "Password and password confirmation must match.", + "ParentalRating": "Parental rating", + "PackageInstallFailed": "{0} (version {1}) installation failed.", + "PackageInstallCompleted": "{0} (version {1}) installation completed.", + "PackageInstallCancelled": "{0} (version {1}) installation cancelled.", + "OriginalAirDateValue": "Original air date: {0}", + "OptionWeekly": "Weekly", + "OptionWeekends": "Weekends", + "OptionWeekdays": "Weekdays", + "OptionWakeFromSleep": "Wake from sleep", + "OptionUnairedEpisode": "Unaired Episodes", + "OptionTrackName": "Track Name", + "OptionSubstring": "Substring", + "OptionSpecialEpisode": "Specials", + "OptionSaveMetadataAsHiddenHelp": "Changing this will apply to new metadata saved going forward. Existing metadata files will be updated the next time they are saved by the server.", + "OptionSaveMetadataAsHidden": "Save metadata and images as hidden files", + "OptionResumable": "Resumable", + "OptionResElement": "res element", + "OptionRequirePerfectSubtitleMatchHelp": "Requiring a perfect match will filter subtitles to include only those that have been tested and verified with your exact video file. Unchecking this will increase the likelihood of subtitles being downloaded, but will increase the chances of mistimed or incorrect subtitle text.", + "OptionRequirePerfectSubtitleMatch": "Only download subtitles that are a perfect match for my video files", + "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.", + "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding", + "OptionRegex": "Regex", + "OptionPremiereDate": "Premiere Date", + "OptionPlayCount": "Play Count", + "OptionPlainVideoItemsHelp": "All videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".", + "OptionPlainVideoItems": "Display all videos as plain video items", + "OptionPlainStorageFoldersHelp": "All folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".", + "OptionParentalRating": "Parental Rating", + "OptionOnInterval": "On an interval", + "OptionNew": "New…", + "OptionMissingEpisode": "Missing Episodes", + "OptionMax": "Max", + "OptionLoginAttemptsBeforeLockoutHelp": "A value of zero means inheriting the default of three attempts for normal users and five for administrators. Setting this to -1 will disable the feature.", + "OptionLoginAttemptsBeforeLockout": "Determines how many incorrect login attempts can be made before lockout occurs.", + "OptionDatePlayed": "Date Played", + "OptionAutomaticallyGroupSeriesHelp": "Series that are spread across multiple folders within this library will be automatically merged into a single series.", + "OptionAutomaticallyGroupSeries": "Automatically merge series that are spread across multiple folders", + "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding", + "OptionAllowVideoPlaybackRemuxing": "Allow video playback that requires conversion without re-encoding", + "OptionAllowUserToManageServer": "Allow this user to manage the server", + "OptionAllowSyncTranscoding": "Allow media downloading and syncing that requires transcoding", + "OptionAllowRemoteSharedDevicesHelp": "DLNA devices are considered shared until a user begins controlling them.", + "OptionAllowRemoteSharedDevices": "Allow remote control of shared devices", + "OptionAllowRemoteControlOthers": "Allow remote control of other users", + "OptionAllowMediaPlaybackTranscodingHelp": "Restricting access to transcoding may cause playback failures in clients due to unsupported media formats.", + "OptionAllowManageLiveTv": "Allow Live TV recording management", + "OptionAllowLinkSharingHelp": "Only web pages containing media information are shared. Media files are never shared publicly. Shares are time-limited and will expire after {0} days.", + "OptionAllowLinkSharing": "Allow social media sharing", + "OptionAllowContentDownloading": "Allow media downloading and syncing", + "OptionAllowBrowsingLiveTv": "Allow Live TV access", + "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding", + "OptionAllUsers": "All users", + "Option3D": "3D", + "OnlyImageFormats": "Only Image Formats (VOBSUB, PGS, SUB)", + "OnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.", + "Normal": "Normal", + "None": "None", + "NoSubtitlesHelp": "Subtitles will not be loaded by default. They can still be turned on manually during playback.", + "MessageNoPluginConfiguration": "This plugin has no settings to configure.", + "MessageNoNextUpItems": "None found. Start watching your shows!", + "No": "No", + "NextUp": "Next Up", + "NewEpisodesOnly": "New episodes only", + "NewCollection": "New Collection", + "Never": "Never", + "MySubtitles": "My Subtitles", + "Mute": "Mute", + "MusicLibraryHelp": "Review the {0}music naming guide{1}.", + "Monday": "Monday", + "MinutesBefore": "minutes before", + "MetadataSettingChangeHelp": "Changing metadata settings will affect new content added going forward. To refresh existing content, open the detail screen and click the refresh button, or perform bulk refreshes using the metadata manager.", + "MetadataManager": "Metadata Manager", + "MessagePluginInstallDisclaimer": "Plugins built by community members are a great way to enhance your experience with additional features and benefits. Before installing, please be aware of the effects they may have on your server, such as longer library scans, additional background processing, and decreased system stability.", + "MessagePluginConfigurationRequiresLocalAccess": "To configure this plugin please sign in to your local server directly.", + "MessagePleaseWait": "Please wait. This may take a minute.", + "MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.", + "MessagePlayAccessRestricted": "Playback of this content is currently restricted. Please contact your server administrator for more information.", + "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.", + "MessageNothingHere": "Nothing here.", + "MessageNoTrailersFound": "Install the trailers channel to enhance your movie experience by adding a library of internet trailers.", + "MessageNoServersAvailable": "No servers have been found using the automatic server discovery.", + "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", + "MessageNoAvailablePlugins": "No available plugins.", + "MessageInvalidUser": "Invalid username or password. Please try again.", + "MessageInvalidForgotPasswordPin": "An invalid or expired pin code was entered. Please try again.", + "MessageImageTypeNotSelected": "Please select an image type from the drop-down menu.", + "MessageImageFileTypeAllowed": "Only JPEG and PNG files are supported.", + "MessageForgotPasswordInNetworkRequired": "Please try again within your home network to initiate the password reset process.", + "MessageForgotPasswordFileCreated": "The following file has been created on your server and contains instructions on how to proceed:", + "MessageDeleteTaskTrigger": "Are you sure you wish to delete this task trigger?", + "MessageCreateAccountAt": "Create an account at {0}", + "MessageContactAdminToResetPassword": "Please contact your system administrator to reset your password.", + "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this API key? The application's connection to this server will be abruptly terminated.", + "MessageConfirmRestart": "Are you sure you wish to restart Jellyfin?", + "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?", + "MessageConfirmDeleteTunerDevice": "Are you sure you wish to delete this device?", + "MessageConfirmDeleteGuideProvider": "Are you sure you wish to delete this guide provider?", + "MessageAlreadyInstalled": "This version is already installed.", + "Menu": "Menu", + "MediaIsBeingConverted": "The media is being converted into a format that is compatible with the device that is playing the media.", + "MediaInfoTimestamp": "Timestamp", + "MediaInfoSize": "Size", + "MediaInfoSampleRate": "Sample rate", + "MediaInfoResolution": "Resolution", + "MediaInfoRefFrames": "Ref frames", + "MediaInfoProfile": "Profile", + "MediaInfoPixelFormat": "Pixel format", + "MediaInfoPath": "Path", + "MediaInfoLevel": "Level", + "MediaInfoLayout": "Layout", + "MediaInfoAspectRatio": "Aspect ratio", + "MediaInfoAnamorphic": "Anamorphic", + "MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.", + "MarkUnplayed": "Mark unplayed", + "MarkPlayed": "Mark played", + "MapChannels": "Map Channels", + "ManageLibrary": "Manage library", + "Logo": "Logo", + "LiveBroadcasts": "Live broadcasts", + "Live": "Live", + "List": "List", + "LibraryAccessHelp": "Select the libraries to share with this user. Administrators will be able to edit all folders using the metadata manager.", + "LeaveBlankToNotSetAPassword": "You can leave this field blank to set no password.", + "LearnHowYouCanContribute": "Learn how you can contribute.", + "LanNetworksHelp": "Comma separated list of IP addresses or IP/netmask entries for networks that will be considered on local network when enforcing bandwidth restrictions. If set, all other IP addresses will be considered to be on the external network and will be subject to the external bandwidth restrictions. If left blank, only the server's subnet is considered to be on the local network.", + "LabelffmpegPathHelp": "The path to the ffmpeg application file or folder containing ffmpeg.", + "LabelffmpegPath": "FFmpeg path:", + "LabelYear": "Year:", + "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.", + "LabelXDlnaDoc": "X-DLNA doc:", + "LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.", + "LabelWeb": "Web:", + "DashboardServerName": "Server: {0}", + "DashboardVersionNumber": "Version: {0}", + "LabelVersionInstalled": "{0} installed", + "LabelVaapiDeviceHelp": "This is the render node that is used for hardware acceleration.", + "LabelVaapiDevice": "VA API Device:", + "LabelUsername": "Username:", + "LabelUserRemoteClientBitrateLimitHelp": "Override the default global value set in server playback settings.", + "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.", + "LabelUserLibrary": "User library:", + "LabelUserAgent": "User agent:", + "LabelUser": "User:", + "LabelUseNotificationServices": "Use the following services:", + "LabelTypeText": "Text", + "LabelTunerIpAddress": "Tuner IP Address:", + "LabelTriggerType": "Trigger Type:", + "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.", + "LabelTranscodingThreadCount": "Transcoding thread count:", + "LabelTranscodingFramerate": "Transcoding framerate:", + "LabelTranscodes": "Transcodes:", + "LabelTranscodingTempPathHelp": "Specify a custom path for the transcode files served to clients. Leave blank to use the server default.", + "LabelTranscodePath": "Transcode path:", + "LabelTrackNumber": "Track number:", + "LabelTitle": "Title:", + "LabelTagline": "Tagline:", + "LabelTag": "Tag:", + "LabelTVHomeScreen": "TV mode home screen:", + "LabelSupportedMediaTypes": "Supported Media Types:", + "LabelSubtitlePlaybackMode": "Subtitle mode:", + "LabelSubtitleFormatHelp": "Example: srt", + "LabelSubtitleDownloaders": "Subtitle downloaders:", + "LabelStopping": "Stopping", + "LabelStopWhenPossible": "Stop when possible:", + "LabelStatus": "Status:", + "LabelStartWhenPossible": "Start when possible:", + "LabelSpecialSeasonsDisplayName": "Special season display name:", + "LabelSource": "Source:", + "LabelSortBy": "Sort by:", + "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.", + "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery and decrease the likelihood of video transcoding.", + "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.", + "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language", + "LabelSkipBackLength": "Skip back length:", + "LabelSize": "Size:", + "LabelSimultaneousConnectionLimit": "Simultaneous stream limit:", + "LabelServerHost": "Host:", + "LabelSerialNumber": "Serial number", + "LabelSendNotificationToUsers": "Send the notification to:", + "LabelSelectFolderGroupsHelp": "Folders that are unchecked will be displayed by themselves in their own view.", + "LabelSelectFolderGroups": "Automatically group content from the following folders into views such as Movies, Music and TV:", + "LabelSeasonNumber": "Season number:", + "LabelScreensaver": "Screensaver:", + "EnableFasterAnimations": "Faster animations", + "EnableFasterAnimationsHelp": "Use faster animations and transitions", + "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", + "LabelSaveLocalMetadataHelp": "Saving artwork into media folders will put them in a place where they can be easily edited.", + "LabelRuntimeMinutes": "Runtime:", + "LabelRemoteClientBitrateLimitHelp": "An optional per-stream bitrate limit for all out of network devices. This is useful to prevent devices from requesting a higher bitrate than your internet connection can handle. This may result in increased CPU load on your server in order to transcode videos on the fly to a lower bitrate.", + "LabelRemoteClientBitrateLimit": "Internet streaming bitrate limit (Mbps):", + "LabelReleaseDate": "Release date:", + "LabelRefreshMode": "Refresh mode:", + "LabelRecord": "Record:", + "LabelReasonForTranscoding": "Reason for transcoding:", + "LabelPublicHttpsPort": "Public HTTPS port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local HTTP port.", + "LabelPublicHttpPort": "Public HTTP port number:", + "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.", + "LabelDidlMode": "DIDL mode:", + "LabelDefaultUser": "Default user:", + "LabelDefaultScreen": "Default screen:", + "LabelDeathDate": "Death date:", + "LabelDay": "Day:", + "LabelDateTimeLocale": "Date time locale:", + "LabelCustomDeviceDisplayNameHelp": "Supply a custom display name or leave empty to use the name reported by the device.", + "HeaderYears": "Years", + "HeaderVideos": "Videos", + "HeaderVideoTypes": "Video Types", + "Series": "Series", + "NewEpisodes": "New episodes", + "NewCollectionNameExample": "Example: Star Wars Collection", + "MinutesAfter": "minutes after", + "Metadata": "Metadata", + "MessageFileReadError": "There was an error reading the file. Please try again.", + "MessageEnablingOptionLongerScans": "Enabling this option may result in significantly longer library scans.", + "MessageConfirmRecordingCancellation": "Cancel recording?", + "MessageConfirmProfileDeletion": "Are you sure you wish to delete this profile?", + "OnlyForcedSubtitles": "Only Forced", + "Off": "Off", + "NumLocationsValue": "{0} folders", + "Name": "Name", + "MovieLibraryHelp": "Review the {0}movie naming guide{1}.", + "MoveRight": "Move right", + "MoveLeft": "Move left", + "MoreMediaInfo": "Media Info", + "MoreUsersCanBeAddedLater": "More users can be added later from within the dashboard.", + "MoreFromValue": "More from {0}", + "MessageDownloadQueued": "Download queued.", + "MediaInfoLanguage": "Language", + "MediaInfoInterlaced": "Interlaced", + "MediaInfoFramerate": "Framerate", + "MediaInfoForced": "Forced", + "MediaInfoExternal": "External", + "MediaInfoDefault": "Default", + "MediaInfoContainer": "Container", + "MediaInfoCodecTag": "Codec tag", + "MediaInfoCodec": "Codec", + "ManageRecording": "Manage recording", + "LiveTV": "Live TV", + "LatestFromLibrary": "Latest {0}", + "Large": "Large", + "LabelZipCode": "Postcode:", + "LabelYoureDone": "You're Done!", + "LabelVideoCodec": "Video codec:", + "LabelVideoBitrate": "Video bitrate:", + "DashboardArchitecture": "Architecture: {0}", + "DashboardOperatingSystem": "Operating System: {0}", + "LabelVersion": "Version:", + "LabelValue": "Value:", + "LabelUserLoginAttemptsBeforeLockout": "Failed login attempts before user is locked out:", + "LabelTranscodingProgress": "Transcoding progress:", + "LabelTimeLimitHours": "Time limit (hours):", + "LabelTime": "Time:", + "LabelTheme": "Theme:", + "LabelTextSize": "Text size:", + "LabelSportsCategories": "Sports categories:", + "LabelSortTitle": "Sort title:", + "LabelSortOrder": "Sort order:", + "LabelSonyAggregationFlags": "Sony aggregation flags:", + "LabelSkipForwardLength": "Skip forward length:", + "LabelSelectUsers": "Select users:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local HTTPS port.", + "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", + "LabelProtocolInfo": "Protocol info:", + "LabelProfileContainer": "Container:", + "LabelPostProcessorArguments": "Post-processor command line arguments:", + "LabelPlayMethod": "Play method:", + "LabelPlaylist": "Playlist:", + "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language", + "LabelPlaceOfBirth": "Place of birth:", + "LabelOverview": "Overview:", + "LabelOriginalAspectRatio": "Original aspect ratio:", + "LabelMusicStreamingTranscodingBitrateHelp": "Specify a maximum bitrate when streaming music.", + "LabelMetadataDownloadLanguage": "Preferred download language:", + "LabelMetadata": "Metadata:", + "LabelKeepUpTo": "Keep up to:", + "LabelFinish": "Finish", + "LabelFailed": "Failed", + "LabelExtractChaptersDuringLibraryScan": "Extract chapter images during the library scan", + "LabelEndDate": "End date:", + "LabelEnableSingleImageInDidlLimit": "Limit to single embedded image", + "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging", + "UninstallPluginConfirmation": "Are you sure you wish to uninstall {0}?", + "Uniform": "Uniform", + "TvLibraryHelp": "Review the {0}TV naming guide{1}.", + "Tuesday": "Tuesday", + "Transcoding": "Transcoding", + "ThemeVideos": "Theme videos", + "ThemeSongs": "Theme songs", + "TellUsAboutYourself": "Tell us about yourself", + "TagsValue": "Tags: {0}", + "Tags": "Tags", + "TabUpcoming": "Upcoming", + "LabelDisplayMode": "Display mode:", + "LabelDisplayLanguageHelp": "Translating Jellyfin is an ongoing project.", + "LabelDisplayLanguage": "Display language:", + "LabelDiscNumber": "Disc number:", + "LabelDeviceDescription": "Device description", + "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.", + "TabStreaming": "Streaming", + "TabProfiles": "Profiles", + "TabPlugins": "Plugins", + "TabNfoSettings": "NFO Settings", + "TabNetworking": "Networking", + "TabLatest": "Latest", + "TabDashboard": "Dashboard", + "TabContainers": "Containers", + "TabCodecs": "Codecs", + "Sort": "Sort", + "Smaller": "Smaller", + "SmallCaps": "Small Caps", + "Small": "Small", + "SkipEpisodesAlreadyInMyLibrary": "Don't record episodes that are already in my library", + "RecommendationBecauseYouLike": "Because you like {0}", + "RecentlyWatched": "Recently watched", + "OptionEveryday": "Every day", + "OptionEstimateContentLength": "Estimate content length when transcoding", + "OptionAllowMediaPlayback": "Allow media playback", + "Next": "Next", + "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?", + "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?", + "LabelTypeMetadataDownloaders": "{0} metadata downloaders:", + "LabelType": "Type:", + "LabelTunerType": "Tuner type:", + "LabelServerName": "Server name:", + "LabelServerHostHelp": "192.168.1.100:8096 or https://myserver.com", + "LabelSeriesRecordingPath": "Series recording path:", + "LabelRecordingPathHelp": "Specify the default location to save recordings. If left empty, the server's program data folder will be used.", + "LabelRecordingPath": "Default recording path:", + "LabelAlbumArtMaxWidth": "Album art max width:", + "LabelCustomCssHelp": "Apply your own custom styles on the web interface.", + "LabelBlastMessageIntervalHelp": "Determines the duration in seconds between blast alive messages.", + "LabelBlastMessageInterval": "Alive message interval", + "LabelBitrate": "Bitrate:", + "LabelAudioSampleRate": "Audio sample rate:", + "LabelAlbumArtMaxHeight": "Album art max height:", + "LabelAccessStart": "Start time:", + "Label3DFormat": "3D format:", + "Thumb": "Thumb", + "ProductionLocations": "Production locations", + "OptionProtocolHttp": "HTTP", + "OptionEnableForAllTuners": "Enable for all tuner devices", + "MessageNoPluginsInstalled": "You have no plugins installed.", + "LabelXDlnaCap": "X-DLNA cap:", + "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains embedded subtitles", + "LabelManufacturer": "Manufacturer:", + "LabelLoginDisclaimer": "Login disclaimer:", + "LabelLocalHttpServerPortNumber": "Local HTTP port number:", + "LabelKodiMetadataEnablePathSubstitution": "Enable path substitution", + "LabelKodiMetadataDateFormatHelp": "All dates within NFO files will be parsed using this format.", + "LabelKodiMetadataDateFormat": "Release date format:", + "LabelKidsCategories": "Children's categories:", + "LabelInNetworkSignInWithEasyPasswordHelp": "Use the easy pin code to sign in to clients within your local network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelHardwareAccelerationTypeHelp": "Hardware acceleration requires additional configuration.", + "LabelEnableHardwareDecodingFor": "Enable hardware decoding for:", + "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play content.", + "LabelEnableDlnaDebugLoggingHelp": "Create large log files and should only be used as needed for troubleshooting purposes.", + "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches.", + "LabelEnableAutomaticPortMapHelp": "Automatically forward public ports on your router to local ports on your server via UPnP. This may not work with some router models or network configurations. Changes will not apply until after a server restart.", + "InstallingPackage": "Installing {0} (version {1})", + "ImportMissingEpisodesHelp": "Information about missing episodes will be imported into your database and displayed within seasons and series. This may cause significantly longer library scans.", + "HeaderSubtitleAppearance": "Subtitle Appearance", + "LabelProtocol": "Protocol:", + "LabelProfileVideoCodecs": "Video codecs:", + "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.", + "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.", + "LabelProfileAudioCodecs": "Audio codecs:", + "LabelPreferredSubtitleLanguage": "Preferred subtitle language:", + "LabelPreferredDisplayLanguage": "Preferred display language:", + "LabelPostProcessor": "Post-processing application:", + "LabelPlayer": "Player:", + "LabelPersonRoleHelp": "Example: Ice cream truck driver", + "LabelPersonRole": "Role:", + "LabelPath": "Path:", + "LabelPassword": "Password:", + "LabelParentalRating": "Parental rating:", + "LabelParentNumber": "Parent number:", + "LabelOptionalNetworkPath": "Shared network folder:", + "LabelNewsCategories": "News categories:", + "LabelNewPasswordConfirm": "New password confirm:", + "LabelNewPassword": "New password:", + "LabelNewName": "New name:", + "LabelName": "Name:", + "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:", + "LabelMoviePrefix": "Movie prefix:", + "LabelMovieCategories": "Movie categories:", + "LabelMonitorUsers": "Monitor activity from:", + "LabelModelUrl": "Model URL", + "LabelModelNumber": "Model number", + "LabelModelName": "Model name", + "LabelModelDescription": "Model description", + "LabelMinScreenshotDownloadWidth": "Minimum screenshot download width:", + "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time.", + "LabelMinResumePercentage": "Minimum resume percentage:", + "LabelMinResumeDurationHelp": "The shortest video length in seconds that will save playback location and let you resume.", + "LabelMinResumeDuration": "Minimum resume duration:", + "LabelMinBackdropDownloadWidth": "Minimum backdrop download width:", + "LabelMethod": "Method:", + "LabelMetadataSaversHelp": "Choose the file formats to use when saving your metadata.", + "LabelMetadataSavers": "Metadata savers:", + "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.", + "LabelMetadataReaders": "Metadata readers:", + "LabelMetadataPath": "Metadata path:", + "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time.", + "LabelMaxResumePercentage": "Maximum resume percentage:", + "LabelMaxChromecastBitrate": "Chromecast streaming quality:", + "LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:", + "LabelMatchType": "Match type:", + "LabelManufacturerUrl": "Manufacturer URL", + "LabelLoginDisclaimerHelp": "A message that will be displayed at the bottom of the login page.", + "LabelLockItemToPreventChanges": "Lock this item to prevent future changes", + "LabelLocalHttpServerPortNumberHelp": "The TCP port number for the HTTP server.", + "LabelLineup": "Lineup:", + "LabelLanguage": "Language:", + "LabelLanNetworks": "LAN networks:", + "LabelKodiMetadataUser": "Save user watch data to NFO files for:", + "LabelKodiMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Kodi guidelines.", + "LabelKodiMetadataSaveImagePaths": "Save image paths within nfo files", + "LabelKodiMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.", + "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", + "LabelImageType": "Image type:", + "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.", + "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.", + "LabelIconMaxWidth": "Icon maximum width:", + "LabelIconMaxHeight": "Icon maximum height:", + "LabelHttpsPortHelp": "The TCP port number for the HTTPS server.", + "LabelHttpsPort": "Local HTTPS port number:", + "LabelHomeScreenSectionValue": "Home screen section {0}:", + "LabelHomeNetworkQuality": "Home network quality:", + "LabelHardwareAccelerationType": "Hardware acceleration:", + "LabelEncoderPreset": "H264 and H265 encoding preset:", + "LabelH264Crf": "H264 encoding CRF:", + "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies in a collection will be displayed as one grouped item.", + "LabelGroupMoviesIntoCollections": "Group movies into collections", + "LabelServerNameHelp": "This name will be used to identify the server and will default to the server's hostname.", + "LabelFriendlyName": "Friendly name:", + "LabelFormat": "Format:", + "LabelForgotPasswordUsernameHelp": "Enter your username, if you remember it.", + "LabelFont": "Font:", + "LabelExtractChaptersDuringLibraryScanHelp": "Generate chapter images when videos are imported during the library scan. Otherwise, they will be extracted during the chapter images scheduled task, allowing the regular library scan to complete faster.", + "LabelBaseUrlHelp": "Add a custom subdirectory to the server URL. For example: http://example.com/<baseurl>", + "LabelEveryXMinutes": "Every:", + "LabelEvent": "Event:", + "LabelEpisodeNumber": "Episode number:", + "LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.", + "LabelEnableRealtimeMonitorHelp": "Changes to files will be processed immediately on supported file systems.", + "LabelEnableRealtimeMonitor": "Enable real time monitoring", + "LabelEnableDlnaServer": "Enable DLNA server", + "LabelEnableDlnaPlayToHelp": "Detect devices within your network and offer the ability to control them remotely.", + "LabelEnableDlnaPlayTo": "Enable DLNA Play To", + "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval", + "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.", + "LabelEnableBlastAliveMessages": "Blast alive messages", + "LabelEnableAutomaticPortMap": "Enable automatic port mapping", + "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.", + "LabelEmbedAlbumArtDidl": "Embed album art in Didl", + "LabelEasyPinCode": "Easy pin code:", + "LabelDynamicExternalId": "{0} Id:", + "LabelDropShadow": "Drop shadow:", + "LabelDropImageHere": "Drop image here, or click to browse.", + "LabelDownloadLanguages": "Download languages:", + "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. A value of one will preserve the original volume.", + "LabelDownMixAudioScale": "Audio boost when downmixing:", + "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in", + "LabelDisplayOrder": "Display order:", + "LabelDisplayName": "Display name:", + "LabelDateAddedBehaviorHelp": "If a metadata value is present, it will always be used before either of these options.", + "LabelCustomCss": "Custom CSS:", + "LabelCustomCertificatePathHelp": "Path to a PKCS #12 file containing a certificate and private key to enable TLS support on a custom domain.", + "LabelCurrentPassword": "Current password:", + "LabelCriticRating": "Critic rating:", + "LabelCountry": "Country:", + "LabelContentType": "Content type:", + "LabelCommunityRating": "Community rating:", + "LabelCertificatePassword": "Certificate password:", + "LabelCancelled": "Cancelled", + "LabelCachePathHelp": "Specify a custom location for server cache files such as images. Leave blank to use the server default.", + "LabelCachePath": "Cache path:", + "LabelCache": "Cache:", + "LabelBurnSubtitles": "Burn subtitles:", + "LabelBlockContentWithTags": "Block items with tags:", + "LabelBirthYear": "Birth year:", + "LabelBirthDate": "Birth date:", + "LabelBindToLocalNetworkAddress": "Bind to local network address:", + "LabelAutomaticallyRefreshInternetMetadataEvery": "Automatically refresh metadata from the internet:", + "LabelAuthProvider": "Authentication Provider:", + "LabelAudioLanguagePreference": "Preferred audio language:", + "LabelAudioCodec": "Audio codec:", + "LabelAudioChannels": "Audio channels:", + "LabelAudioBitrate": "Audio bitrate:", + "LabelAudioBitDepth": "Audio bit depth:", + "LabelArtistsHelp": "Separate multiple artists with a semicolon.", + "LabelArtists": "Artists:", + "LabelAppName": "App name", + "LabelAllowedRemoteAddressesMode": "Remote IP address filter mode:", + "LabelAllowedRemoteAddresses": "Remote IP address filter:", + "LabelAllowHWTranscoding": "Allow hardware transcoding", + "LabelAlbumArtists": "Album artists:", + "LabelAlbumArtPN": "Album art PN:", + "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some devices require a specific value, regardless of the size of the image.", + "LabelAirsBeforeSeason": "Airs before season:", + "LabelAirsBeforeEpisode": "Airs before episode:", + "LabelAirsAfterSeason": "Airs after season:", + "LabelAirTime": "Air time:", + "LabelAirDays": "Air days:", + "LabelAccessEnd": "End time:", + "LabelAccessDay": "Day of week:", + "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", + "Kids": "Kids", + "Items": "Items", + "ItemCount": "{0} items", + "InstantMix": "Instant mix", + "Images": "Images", + "Identify": "Identify", + "Horizontal": "Horizontal", + "Home": "Home", + "HideWatchedContentFromLatestMedia": "Hide watched content from latest media", + "Hide": "Hide", + "Help": "Help", + "HeaderXmlSettings": "XML Settings", + "HeaderXmlDocumentAttributes": "XML Document Attributes", + "HeaderXmlDocumentAttribute": "XML Document Attribute", + "HeaderVideoType": "Video Type", + "HeaderVideoQuality": "Video Quality", + "HeaderUsers": "Users", + "HeaderUser": "User", + "HeaderUploadImage": "Upload Image", + "HeaderUpcomingOnTV": "Upcoming On TV", + "HeaderTypeText": "Enter Text", + "HeaderTypeImageFetchers": "{0} Image Fetchers", + "HeaderTuners": "Tuners", + "HeaderTunerDevices": "Tuner Devices", + "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.", + "HeaderTranscodingProfile": "Transcoding Profile", + "HeaderTracks": "Tracks", + "HeaderThisUserIsCurrentlyDisabled": "This user is currently disabled", + "HeaderTaskTriggers": "Task Triggers", + "HeaderSystemDlnaProfiles": "System Profiles", + "HeaderSubtitleProfilesHelp": "Subtitle profiles describe the subtitle formats supported by the device.", + "HeaderSubtitleProfiles": "Subtitle Profiles", + "HeaderSubtitleProfile": "Subtitle Profile", + "Overview": "Overview", + "LabelLogs": "Logs:", + "Whitelist": "Whitelist", + "ServerNameIsRestarting": "The server at {0} is restarting.", + "OptionProtocolHls": "HTTP Live Streaming", + "OneChannel": "One channel", + "MediaInfoChannels": "Channels", + "MediaInfoBitDepth": "Bit depth", + "LabelAlbum": "Album:", + "LabelProfileCodecs": "Codecs:", + "LabelPasswordRecoveryPinCode": "Pin code:", + "LabelPasswordResetProvider": "Password Reset Provider:", + "LabelPasswordConfirm": "Password (confirm):", + "LabelOriginalTitle": "Original title:", + "LabelOptionalNetworkPathHelp": "If this folder is shared on your network, supplying the network share path can allow clients on other devices to access media files directly. For example, {0} or {1}.", + "LabelNumberOfGuideDaysHelp": "Downloading more days worth of guide data provides the ability to schedule out further in advance and view more listings, but it will also take longer to download. Auto will choose based on the number of channels.", + "LabelNumberOfGuideDays": "Number of days of guide data to download:", + "LabelNumber": "Number:", + "LabelNotificationEnabled": "Enable this notification", + "SeriesDisplayOrderHelp": "Order episodes by air date, DVD order, or absolute numbering.", + "PleaseEnterNameOrId": "Please enter a name or an external ID.", + "OptionTvdbRating": "TVDB Rating", + "OptionDvd": "DVD", + "MessageDirectoryPickerLinuxInstruction": "For Linux on Arch Linux, CentOS, Debian, Fedora, openSUSE, or Ubuntu, you must grant the service user at least read access to your storage locations.", + "LabelCustomCertificatePath": "Custom SSL certificate path:", + "LabelBindToLocalNetworkAddressHelp": "Override the local IP address for the HTTP server. If left empty, the server will bind to all available addresses. Changing this value requires a restart.", + "LabelAppNameExample": "Example: Sickbeard, Sonarr", + "HttpsRequiresCert": "To enable secure connections, you will need to supply a trusted SSL certificate, such as Let's Encrypt. Please either supply a certificate, or disable secure connections.", + "Yesterday": "Yesterday", + "Yes": "Yes", + "XmlTvPathHelp": "A path to an XMLTV file. Jellyfin will read this file and periodically check it for updates. You are responsible for creating and updating the file.", + "WelcomeToProject": "Welcome to Jellyfin!", + "Wednesday": "Wednesday", + "Watched": "Watched", + "ViewPlaybackInfo": "View playback info", + "ViewAlbum": "View album", + "SubtitleAppearanceSettingsAlsoPassedToCastDevices": "These settings also apply to any Chromecast playback started by this device.", + "Studios": "Studios", + "StopRecording": "Stop recording", + "Sports": "Sports", + "OptionPlainStorageFolders": "Display all folders as plain storage folders", + "OptionDisableUserHelp": "The server will not allow any connections from this user. Existing connections will be abruptly terminated.", + "OptionDateAdded": "Date Added", + "OptionDaily": "Daily", + "OptionCommunityRating": "Community Rating", + "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders.", + "LabelSelectVersionToInstall": "Select version to install:", + "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata.", + "OptionLikes": "Likes", + "OptionIsSD": "SD", + "OptionIsHD": "HD", + "OptionImdbRating": "IMDb Rating", + "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests", + "OptionHlsSegmentedSubtitles": "HLS segmented subtitles", + "OptionHideUserFromLoginHelp": "Useful for private or hidden administrator accounts. The user will need to sign in manually by entering their username and password.", + "OptionHideUser": "Hide this user from login screens", + "OptionHasThemeVideo": "Theme Video", + "OptionHasThemeSong": "Theme Song", + "OptionExtractChapterImage": "Enable chapter image extraction", + "OptionExternallyDownloaded": "External download", + "OptionEquals": "Equals", + "OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.", + "OptionEnableM2tsMode": "Enable M2ts mode", + "OptionEnableExternalContentInSuggestions": "Enable external content in suggestions", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEmbedSubtitles": "Embed within container", + "OptionDownloadImagesInAdvanceHelp": "By default, most images are only downloaded when requested by a client. Enable this option to download all images in advance, as new media is imported. This may cause significantly longer library scans.", + "OptionDownloadImagesInAdvance": "Download images in advance", + "OptionDisplayFolderView": "Display a folder view to show plain media folders", + "LabelMovieRecordingPath": "Movie recording path:", + "LabelMoviePrefixHelp": "If a prefix is applied to movie titles, enter it here so the server can handle it properly.", + "LabelMessageTitle": "Message title:", + "LabelMessageText": "Message text:", + "LabelMaxStreamingBitrateHelp": "Specify a maximum bitrate when streaming.", + "LabelMaxStreamingBitrate": "Maximum streaming quality:", + "LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:", + "LabelMaxParentalRating": "Maximum allowed parental rating:", + "LabelFolder": "Folder:", + "LabelBaseUrl": "Base URL:", + "Up": "Up", + "SearchForCollectionInternetMetadata": "Search the internet for artwork and metadata", + "ValueOneSeries": "1 series", + "MediaInfoBitrate": "Bitrate", + "LabelPostProcessorArgumentsHelp": "Use {path} as the path to the recording file.", + "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart to extrathumbs field", + "LabelInternetQuality": "Internet quality:", + "LabelFileOrUrl": "File or URL:", + "LabelDateAdded": "Date added:", + "LabelCustomRating": "Custom rating:", + "LabelCollection": "Collection:", + "LabelChannels": "Channels:", + "LabelCertificatePasswordHelp": "If your certificate requires a password, please enter it here.", + "ValueOneMovie": "1 movie", + "ValueOneEpisode": "1 episode", + "ValueEpisodeCount": "{0} episodes", + "TabParentalControl": "Parental Control", + "SkipEpisodesAlreadyInMyLibraryHelp": "Episodes will be compared using season and episode numbers, when available.", + "RefreshQueued": "Refresh queued.", + "Play": "Play", + "PasswordResetProviderHelp": "Choose a password reset provider to be used when this user requests a password reset.", + "OptionReleaseDate": "Release Date", + "OptionDisplayFolderViewHelp": "Display folders alongside your other media libraries. This can be useful if you'd like to have a plain folder view.", + "OptionDislikes": "Dislikes", + "OptionDisableUser": "Disable this user", + "OptionDateAddedImportTime": "Use date scanned into the library", + "OptionDateAddedFileTime": "Use file creation date", + "OptionCustomUsers": "Custom", + "OptionCriticRating": "Critic Rating", + "OptionCaptionInfoExSamsung": "CaptionInfoEx (Samsung)", + "OptionBluray": "Blu-ray", + "OptionAdminUsers": "Administrators", + "NoSubtitleSearchResultsFound": "No results found.", + "News": "News", + "MusicVideo": "Music Video", + "MusicArtist": "Music Artist", + "Mobile": "Mobile", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageUnableToConnectToServer": "We're unable to connect to the selected server right now. Please ensure it is running and try again.", + "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:", + "MessageReenableUser": "See below to reenable", + "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item or the global default value.", + "MessageItemsAdded": "Items added.", + "MessageItemSaved": "Item saved.", + "MessageDirectoryPickerBSDInstruction": "For BSD, you may need to configure storage within your FreeNAS Jail so Jellyfin can access your media.", + "MessageConfirmShutdown": "Are you sure you wish to shutdown the server?", + "LabelSaveLocalMetadata": "Save artwork into media folders", + "LabelPleaseRestart": "Changes will take effect after manually reloading the web client.", + "ValueSongCount": "{0} songs", + "Save": "Save", + "People": "People", + "MusicAlbum": "Music Album", + "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, and Albums. Click the + button to start creating collections.", + "ShowTitle": "Show title", + "HeaderStopRecording": "Stop Recording", + "HeaderStatus": "Status", + "HeaderStartNow": "Start Now", + "HeaderSpecialEpisodeInfo": "Special Episode Info", + "HeaderSortOrder": "Sort Order", + "HeaderSortBy": "Sort By", + "HeaderSetupLibrary": "Setup your media libraries", + "HeaderServerSettings": "Server Settings", + "HeaderSeriesStatus": "Series Status", + "HeaderSeriesOptions": "Series Options", + "HeaderSendMessage": "Send Message", + "HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.", + "HeaderSubtitleDownloads": "Subtitle Downloads", + "HeaderSelectTranscodingPath": "Select Transcoding Temporary Path", + "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.", + "HeaderSelectServerCachePath": "Select Server Cache Path", + "HeaderSelectPath": "Select Path", + "HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to use for metadata. The folder must be writeable.", + "HeaderSelectMetadataPath": "Select Metadata Path", + "HeaderSelectCertificatePath": "Select Certificate Path", + "HeaderSecondsValue": "{0} Seconds", + "HeaderSeasons": "Seasons", + "HeaderScenes": "Scenes", + "HeaderRunningTasks": "Running Tasks", + "HeaderRevisionHistory": "Revision History", + "HeaderResponseProfile": "Response Profile", + "HeaderRemoveMediaLocation": "Remove Media Location", + "HeaderRemoveMediaFolder": "Remove Media Folder", + "HeaderRemoteControl": "Remote Control", + "HeaderRecordingPostProcessing": "Recording Post Processing", + "HeaderRecordingOptions": "Recording Options", + "HeaderRecentlyPlayed": "Recently Played", + "HeaderProfileServerSettingsHelp": "These values control how the server will present itself to clients.", + "HeaderProfileInformation": "Profile Information", + "HeaderPreferredMetadataLanguage": "Preferred Metadata Language", + "HeaderPluginInstallation": "Plugin Installation", + "HeaderPleaseSignIn": "Please sign in", + "HeaderPlaybackError": "Playback Error", + "HeaderPlayback": "Media Playback", + "HeaderPlayOn": "Play On", + "HeaderPlayAll": "Play All", + "HeaderPinCodeReset": "Reset Pin Code", + "HeaderPhotoAlbums": "Photo Albums", + "FetchingData": "Fetching additional data", + "ButtonAddImage": "Add Image", + "OptionRandom": "Random", + "SelectAdminUsername": "Please select a username for the admin account.", + "ButtonSplit": "Split", + "HeaderNavigation": "Navigation", + "OptionForceRemoteSourceTranscoding": "Force transcoding of remote media sources (like LiveTV)", + "MessageConfirmAppExit": "Do you want to exit?", + "LabelVideoResolution": "Video resolution:", + "LabelStreamType": "Stream type:", + "LabelPlayerDimensions": "Player dimensions:", + "LabelDroppedFrames": "Dropped frames:", + "LabelCorruptedFrames": "Corrupted frames:", + "NoCreatedLibraries": "Seems like you haven't created any libraries yet. {0}Would you like to create one now?{1}", + "AskAdminToCreateLibrary": "Ask an administrator to create a library.", + "PlaybackErrorNoCompatibleStream": "This client isn't compatible with the media and the server isn't sending a compatible media format.", + "AllowFfmpegThrottlingHelp": "When a transcode or remux gets far enough ahead from the current playback position, pause the process so it will consume less resources. This is most useful when watching without seeking often. Turn this off if you experience playback issues.", + "AllowFfmpegThrottling": "Throttle Transcodes", + "OnApplicationStartup": "On application startup", + "EveryXHours": "Every {0} hours", + "EveryHour": "Every hour", + "EveryXMinutes": "Every {0} minutes", + "OnWakeFromSleep": "On wake from sleep", + "WeeklyAt": "{0}s at {1}", + "DailyAt": "Daily at {0}", + "LastSeen": "Last seen {0}", + "PersonRole": "as {0}", + "ListPaging": "{0}-{1} of {2}", + "WriteAccessRequired": "Jellyfin requires write access to this folder. Please ensure write access and try again.", + "PathNotFound": "The path could not be found. Please ensure the path is valid and try again.", + "Yadif": "YADIF", + "Bwdif": "BWDIF", + "Season": "Season", + "PreferEmbeddedEpisodeInfosOverFileNames": "Prefer embedded episode information over filenames", + "PreferEmbeddedEpisodeInfosOverFileNamesHelp": "This uses the episode information from the embedded metadata if available.", + "Person": "Person", + "Movie": "Movie", + "LabelLibraryPageSizeHelp": "Sets the amount of items to show on a library page. Set to 0 in order to disable paging.", + "LabelLibraryPageSize": "Library page size:", + "LabelDeinterlaceMethod": "Deinterlacing method:", + "Episode": "Episode", + "DeinterlaceMethodHelp": "Select the deinterlacing method to use when software transcoding interlaced content. When hardware acceleration supporting hardware deinterlacing is enabled the hardware deinterlacer will be used instead of this setting.", + "UseDoubleRateDeinterlacing": "Double the frame rate when deinterlacing", + "UseDoubleRateDeinterlacingHelp": "This setting uses the field rate when deinterlacing, often referred to as bob deinterlacing, which doubles the frame rate of the video to provide full motion like what you would see when viewing interlaced video on a TV.", + "ClientSettings": "Client Settings", + "BoxSet": "Box Set", + "Artist": "Artist", + "AlbumArtist": "Album Artist", + "Album": "Album", + "UnsupportedPlayback": "Jellyfin cannot decrypt content protected by DRM but all content will be attempted regardless, including protected titles. Some files may appear completely black due to encryption or other unsupported features, such as interactive titles.", + "ButtonTogglePlaylist": "Playlist", + "HeaderDVR": "DVR", + "ApiKeysCaption": "List of the currently enabled API keys", + "ButtonCast": "Cast", + "ButtonSyncPlay": "SyncPlay", + "EnableBlurHashHelp": "Images that are still being loaded will be displayed with a blurred placeholder.", + "EnableBlurHash": "Enable blurred placeholders for images", + "TabRepositories": "Repositories", + "SyncPlayAccessHelp": "Select the level of access this user has to the SyncPlay feature. SyncPlay enables to sync playback with other devices.", + "ShowMore": "Show more", + "ShowLess": "Show less", + "SaveChanges": "Save changes", + "MessageSyncPlayErrorMedia": "Failed to enable SyncPlay! Media error.", + "MessageSyncPlayErrorMissingSession": "Failed to enable SyncPlay! Missing session.", + "MessageSyncPlayErrorNoActivePlayer": "No active player found. SyncPlay has been disabled.", + "MessageSyncPlayErrorAccessingGroups": "An error occurred while accessing groups list.", + "MessageSyncPlayLibraryAccessDenied": "Access to this content is restricted.", + "MessageSyncPlayJoinGroupDenied": "Permission required to use SyncPlay.", + "MessageSyncPlayCreateGroupDenied": "Permission required to create a group.", + "MessageSyncPlayGroupDoesNotExist": "Failed to join group because it does not exist.", + "MessageSyncPlayPlaybackPermissionRequired": "Playback permission required.", + "MessageSyncPlayNoGroupsAvailable": "No groups available. Start playing something first.", + "MessageSyncPlayGroupWait": "{0} is buffering…", + "MessageSyncPlayUserLeft": "{0} has left the group.", + "MessageSyncPlayUserJoined": "{0} has joined the group.", + "MessageSyncPlayDisabled": "SyncPlay disabled.", + "MessageSyncPlayEnabled": "SyncPlay enabled.", + "MessageNoGenresAvailable": "Enable some metadata providers to pull genres from the internet.", + "MessageAddRepository": "If you wish to add a repository, click the button next to the header and fill out the requested information.", + "LabelRepositoryNameHelp": "A custom name to distinguish this repository from any others added to your server.", + "LabelRepositoryName": "Repository Name", + "LabelRepositoryUrlHelp": "The location of the repository manifest you want to include.", + "LabelRepositoryUrl": "Repository URL", + "HeaderNewRepository": "New Repository", + "MessageNoRepositories": "No repositories.", + "LabelSyncPlayAccess": "SyncPlay access", + "LabelSyncPlayAccessNone": "Disabled for this user", + "LabelSyncPlayAccessJoinGroups": "Allow user to join groups", + "LabelSyncPlayAccessCreateAndJoinGroups": "Allow user to create and join groups", + "LabelSyncPlayLeaveGroupDescription": "Disable SyncPlay", + "LabelSyncPlayLeaveGroup": "Leave group", + "LabelSyncPlayNewGroupDescription": "Create a new group", + "LabelSyncPlayNewGroup": "New group", + "LabelSyncPlaySyncMethod": "Sync method:", + "LabelSyncPlayPlaybackDiff": "Playback time difference:", + "MillisecondsUnit": "ms", + "LabelSyncPlayTimeOffset": "Time offset with the server:", + "LabelRequireHttpsHelp": "If checked, the server will automatically redirect all requests over HTTP to HTTPS. This has no effect if the server is not listening on HTTPS.", + "LabelRequireHttps": "Require HTTPS", + "LabelStable": "Stable", + "LabelChromecastVersion": "Chromecast Version", + "LabelEnableHttpsHelp": "Listen on the configured HTTPS port. A valid certificate must also be supplied for this to take effect.", + "LabelEnableHttps": "Enable HTTPS", + "HeaderSyncPlayEnabled": "SyncPlay enabled", + "HeaderSyncPlaySelectGroup": "Join a group", + "HeaderServerAddressSettings": "Server Address Settings", + "HeaderRemoteAccessSettings": "Remote Access Settings", + "HeaderHttpsSettings": "HTTPS Settings", + "EnableDetailsBannerHelp": "Display a banner image at the top of the item details page.", + "EnableDetailsBanner": "Details Banner", + "EnableDecodingColorDepth10Vp9": "Enable 10-Bit hardware decoding for VP9", + "EnableDecodingColorDepth10Hevc": "Enable 10-Bit hardware decoding for HEVC", + "ViewAlbumArtist": "View album artist", + "ClearQueue": "Clear queue", + "StopPlayback": "Stop playback", + "ButtonPlayer": "Player", + "Writers": "Writers", + "Preview": "Preview", + "SubtitleVerticalPositionHelp": "Line number where text appears. Positive numbers indicate top down. Negative numbers indicate bottom up.", + "LabelSubtitleVerticalPosition": "Vertical position:", + "PreviousTrack": "Skip to previous", + "MessageGetInstalledPluginsError": "An error occurred while getting the list of currently installed plugins.", + "MessagePluginInstallError": "An error occurred while installing the plugin.", + "PlaybackRate": "Playback Rate", + "NextTrack": "Skip to next", + "LabelUnstable": "Unstable", + "Video": "Video", + "ThumbCard": "Thumb Card", + "Subtitle": "Subtitle", + "SpecialFeatures": "Special Features", + "SelectServer": "Select Server", + "Restart": "Restart", + "ResetPassword": "Reset Password", + "Profile": "Profile", + "PosterCard": "Poster Card", + "Poster": "Poster", + "MusicVideos": "Music Videos", + "Image": "Image", + "Data": "Data", + "LabelMaxMuxingQueueSizeHelp": "Maximum number of packets that can be buffered while waiting for all streams to initialize. Try to increase it if you still encounter \"Too many packets buffered for output stream\" error in ffmpeg logs. The recommended value is 2048.", + "LabelMaxMuxingQueueSize": "Max muxing queue size:", + "LabelTonemappingParamHelp": "Tune the tone mapping algorithm. The recommended and default values are NaN. Generally leave it blank.", + "LabelTonemappingParam": "Tonemapping param:", + "LabelTonemappingPeakHelp": "Override signal/nominal/reference peak with this value. Useful when the embedded peak information in display metadata is not reliable or when tone mapping from a lower range to a higher range. The recommended and default values are 0.", + "LabelTonemappingPeak": "Tonemapping peak:", + "LabelTonemappingThresholdHelp": "The tonemapping algorithm parameters is fine-tuned per each scene. And a threshold is used to detect whether the scene has changed or not. If the distance between the current frame average brightness and the current running average exceeds a threshold value, we would re-calculate scene average and peak brightness. The recommended and default values are 0.8 and 0.2.", + "LabelTonemappingThreshold": "Tonemapping threshold:", + "LabelTonemappingDesatHelp": "Apply desaturation for highlights that exceed this level of brightness. The higher the parameter, the more colour information will be preserved. This setting helps prevent unnaturally blown-out colours for super-highlights, by (smoothly) turning into white instead. This makes images feel more natural, at the cost of reducing information about out-of-range colours. The recommended and default values are 0 and 0.5.", + "LabelTonemappingDesat": "Tonemapping desat:", + "TonemappingRangeHelp": "Select the output colour range. Auto is the same as the input range.", + "LabelTonemappingRange": "Tonemapping range:", + "TonemappingAlgorithmHelp": "Tone mapping can be fine-tuned. If you are not familiar with these options, just keep the default. The recommended value is Reinhard.", + "LabelTonemappingAlgorithm": "Select the Tone mapping algorithm to use:", + "AllowTonemappingHelp": "Tone mapping can transform the dynamic range of a video from HDR to SDR while maintaining image details and colors, which are very important information for representing the original scene. Currently works only when transcoding videos with embedded HDR10 or HLG metadata. If the playback is not smooth or fails, please consider turning off the corresponding hardware decoder.", + "EnableTonemapping": "Enable Tone mapping", + "LabelOpenclDeviceHelp": "This is the OpenCL device that is used for tonemapping. The left side of the dot is the platform number, and the right side is the device number on the platform. The default value is 0.0. The ffmpeg application file containing the OpenCL hardware acceleration method is required.", + "LabelOpenclDevice": "OpenCL Device:", + "LabelColorPrimaries": "Colour primaries:", + "LabelColorTransfer": "Colour transfer:", + "LabelColorSpace": "Colour space:", + "LabelVideoRange": "Video range:", + "MediaInfoColorPrimaries": "Colour primaries", + "MediaInfoColorTransfer": "Colour transfer", + "MediaInfoColorSpace": "Colour space", + "MediaInfoVideoRange": "Video range", + "VideoAudio": "Video Audio", + "QuickConnectNotActive": "Quick connect is not active on this server", + "QuickConnectNotAvailable": "Ask your server administrator to enable quick connect", + "QuickConnectInvalidCode": "Invalid quick connect code", + "QuickConnectDescription": "To sign in with quick connect, select the Quick Connect button on the device you are logging in from and enter the displayed code below.", + "QuickConnectDeactivated": "Quick connect was deactivated before the login request could be approved", + "QuickConnectAuthorizeFail": "Unknown quick connect code", + "QuickConnectAuthorizeSuccess": "Request authorised", + "QuickConnectAuthorizeCode": "Enter code {0} to login", + "QuickConnectActivationSuccessful": "Successfully activated", + "QuickConnect": "Quick Connect", + "Photo": "Photo", + "LabelQuickConnectCode": "Quick connect code:", + "LabelKnownProxies": "Known proxies:", + "LabelIconMaxResHelp": "Maximum resolution of icons exposed via the upnp:icon property.", + "LabelCurrentStatus": "Current status:", + "LabelAlbumArtMaxResHelp": "Maximum resolution of album art exposed via the upnp:albumArtURI property.", + "KnownProxiesHelp": "Comma separated list of IP addresses of known proxies used when connecting to your Jellyfin instance. This is required to make proper use of X-Forwarded-For headers. Requires a reboot after saving.", + "Other": "Other", + "EnableQuickConnect": "Enable quick connect on this server", + "ButtonUseQuickConnect": "Use Quick Connect", + "ButtonActivate": "Activate", + "Authorize": "Authorise", + "EnableAutoCast": "Set as Default", + + + "LabelCreateHttpPortMap": "Enable automatic port mapping for http traffic as well as https.", + "LabelCreateHttpPortMapHelp": "Permit automatic port mapping to create a rule for http traffic in addition to https traffic.", + "HeaderAutoDiscovery": "Network Discovery", + "LabelAutomaticDiscovery": "Enable Auto Discovery:", + "LabelAutomaticDiscoveryHelp": "Enable applications to detect Jellyfin automatically on udp port 7359.", + "LabelAutoDiscoveryTracing": "Enable Auto Discovery tracing.", + "LabelAutoDiscoveryTracingHelp": "When enabled, packets received on the auto discovery port will be logged.", + "HeaderPortRanges": "Firewall and Proxy Settings", + "LabelUDPPortRange": "UDP Communication Range:", + "LabelUDPPortRangeHelp": "Restrict Jellyfin to use this port range when making UDP connections. (Default is 1024 - 645535).
Note: Certain function require fixed ports that may be outside of this range.", + "LabelHDHomerunPortRange": "HD Homerun Range:", + "LabelHDHomerunPortRangeHelp": "Restricts the HD Homerun UDP port range to this value. (Default is 1024 - 645535).", + "LabelPublishedServerUri": "Published Server URIs:", + "LabelPublishedServerUriHelp": "Override the URI used by Jellyfin, based on the interface, or client IP address.", + "HeaderDebugging": "Debugging and Tracing", + "LabelEnableSSDPTracing": "Enable SSDP Tracing:", + "LabelEnableSSDPTracingHelp": "Enable details SSDP network tracing to be logged.
WARNING: This will cause serious performance degradation.", + "LabelSSDPTracingFilter": "SSDP Filter:", + "LabelSSDPTracingFilterHelp": "Optional IP address upon which to filter the logged SSDP traffic.", + "LabelEnableIP6Help": "Enables IPv6 functionality.", + + "LabelEnableIP6": "Enable IPv6:", + "LabelEnableIP4Help": "Enables IPv4 functionality.", + "LabelEnableIP4": "Enable IPv4:", + "HeaderNetworking": "IP Protocols" } diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 41dd4cd507..0d11dbb9a1 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -1,1569 +1,1452 @@ { - "Absolute": "Absolute", - "AccessRestrictedTryAgainLater": "Access is currently restricted. Please try again later.", - "Actor": "Actor", - "Add": "Add", - "AddItemToCollectionHelp": "Add items to collections by searching for them and using their right-click or tap menus to add them to a collection.", - "AddToCollection": "Add to collection", - "AddToPlayQueue": "Add to play queue", - "AddToPlaylist": "Add to playlist", - "AddedOnValue": "Added {0}", - "AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.", - "AirDate": "Air date", - "Aired": "Aired", - "Album": "Album", - "AlbumArtist": "Album Artist", - "Albums": "Albums", - "Alerts": "Alerts", - "All": "All", - "AllChannels": "All channels", - "AllComplexFormats": "All Complex Formats (ASS, SSA, VOBSUB, PGS, SUB, IDX, …)", - "AllEpisodes": "All episodes", - "AllLanguages": "All languages", - "AllLibraries": "All libraries", - "AllowHWTranscodingHelp": "Allow the tuner to transcode streams on the fly. This may help reduce transcoding required by the server.", - "AllowMediaConversion": "Allow media conversion", - "AllowMediaConversionHelp": "Grant or deny access to the convert media feature.", - "AllowOnTheFlySubtitleExtraction": "Allow subtitle extraction on the fly", - "AllowOnTheFlySubtitleExtractionHelp": "Embedded subtitles can be extracted from videos and delivered to clients in plain text, in order to help prevent video transcoding. On some systems this can take a long time and cause video playback to stall during the extraction process. Disable this to have embedded subtitles burned in with video transcoding when they are not natively supported by the client device.", - "AllowFfmpegThrottling": "Throttle Transcodes", - "AllowFfmpegThrottlingHelp": "When a transcode or remux gets far enough ahead from the current playback position, pause the process so it will consume less resources. This is most useful when watching without seeking often. Turn this off if you experience playback issues.", - "AllowRemoteAccess": "Allow remote connections to this Jellyfin Server.", - "AllowRemoteAccessHelp": "If unchecked, all remote connections will be blocked.", - "AllowedRemoteAddressesHelp": "Comma separated list of IP addresses or IP/netmask entries for networks that will be allowed to connect remotely. If left blank, all remote addresses will be allowed.", - "AlwaysPlaySubtitles": "Always Play", - "AlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.", - "AnyLanguage": "Any Language", - "Anytime": "Anytime", - "AroundTime": "Around", - "Art": "Art", - "Artist": "Artist", - "Artists": "Artists", - "AsManyAsPossible": "As many as possible", - "Ascending": "Ascending", - "AskAdminToCreateLibrary": "Ask an administrator to create a library.", - "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", - "Backdrops": "Backdrops", - "Banner": "Banner", - "BirthDateValue": "Born: {0}", - "BirthLocation": "Birth location", - "BirthPlaceValue": "Birth place: {0}", - "Blacklist": "Blacklist", - "BookLibraryHelp": "Audio and text books are supported. Review the {0} book naming guide {1}.", - "Books": "Books", - "Box": "Box", - "BoxSet": "Box Set", - "BoxRear": "Box (rear)", - "Browse": "Browse", - "BrowsePluginCatalogMessage": "Browse our plugin catalog to view available plugins.", - "BurnSubtitlesHelp": "Determines if the server should burn in subtitles when transcoding videos. Avoiding this will greatly improve performance. Select Auto to burn image based formats (VOBSUB, PGS, SUB, IDX, …) and certain ASS or SSA subtitles.", - "ButtonAdd": "Add", - "ButtonAddImage": "Add Image", - "ButtonAddMediaLibrary": "Add Media Library", - "ButtonAddScheduledTaskTrigger": "Add Trigger", - "ButtonAddServer": "Add Server", - "ButtonAddUser": "Add User", - "ButtonArrowDown": "Down", - "ButtonArrowLeft": "Left", - "ButtonArrowRight": "Right", - "ButtonArrowUp": "Up", - "ButtonAudioTracks": "Audio Tracks", - "ButtonBack": "Back", - "ButtonCancel": "Cancel", - "ButtonChangeServer": "Change Server", - "ButtonConnect": "Connect", - "ButtonDelete": "Delete", - "ButtonDeleteImage": "Delete Image", - "ButtonDown": "Down", - "ButtonDownload": "Download", - "ButtonEdit": "Edit", - "ButtonEditImages": "Edit images", - "ButtonEditOtherUserPreferences": "Edit this user's profile, image and personal preferences.", - "ButtonFilter": "Filter", - "ButtonForgotPassword": "Forgot Password", - "ButtonFullscreen": "Fullscreen", - "ButtonGotIt": "Got It", - "ButtonGuide": "Guide", - "ButtonHelp": "Help", - "ButtonHome": "Home", - "ButtonInfo": "Info", - "ButtonLearnMore": "Learn more", - "ButtonLibraryAccess": "Library access", - "ButtonManualLogin": "Manual Login", - "ButtonMore": "More", - "ButtonNetwork": "Network", - "ButtonNew": "New", - "ButtonNextTrack": "Next track", - "ButtonOff": "Off", - "ButtonOk": "Ok", - "ButtonOpen": "Open", - "ButtonParentalControl": "Parental control", - "ButtonPause": "Pause", - "ButtonPlay": "Play", - "ButtonPreviousTrack": "Previous track", - "ButtonProfile": "Profile", - "ButtonQuickStartGuide": "Quick Start Guide", - "ButtonRefresh": "Refresh", - "ButtonRefreshGuideData": "Refresh Guide Data", - "ButtonRemove": "Remove", - "ButtonRename": "Rename", - "ButtonRepeat": "Repeat", - "ButtonResetEasyPassword": "Reset easy pin code", - "ButtonResetPassword": "Reset Password", - "ButtonRestart": "Restart", - "ButtonResume": "Resume", - "ButtonRevoke": "Revoke", - "ButtonSave": "Save", - "ButtonScanAllLibraries": "Scan All Libraries", - "ButtonSearch": "Search", - "ButtonSelectDirectory": "Select Directory", - "ButtonSelectServer": "Select Server", - "ButtonSelectView": "Select view", - "ButtonSend": "Send", - "ButtonSettings": "Settings", - "ButtonShuffle": "Shuffle", - "ButtonShutdown": "Shutdown", - "ButtonSignIn": "Sign In", - "ButtonSignOut": "Sign Out", - "ButtonSort": "Sort", - "ButtonStart": "Start", - "ButtonStop": "Stop", - "ButtonSplit": "Split", - "ButtonSubmit": "Submit", - "ButtonSubtitles": "Subtitles", - "ButtonToggleContextMenu": "More", - "ButtonTogglePlaylist": "Playlist", - "ButtonTrailer": "Trailer", - "ButtonUninstall": "Uninstall", - "ButtonUp": "Up", - "ButtonViewWebsite": "View website", - "ButtonWebsite": "Website", - "CancelRecording": "Cancel recording", - "CancelSeries": "Cancel series", - "Categories": "Categories", - "ChangingMetadataImageSettingsNewContent": "Changes to metadata or artwork downloading settings will only apply to new content added to your library. To apply the changes to existing titles, you'll need to refresh their metadata manually.", - "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.", - "ChannelNameOnly": "Channel {0} only", - "ChannelNumber": "Channel number", - "Channels": "Channels", - "CinemaModeConfigurationHelp": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.", - "ClientSettings": "Client Settings", - "Collections": "Collections", - "ColorPrimaries": "Color primaries", - "ColorSpace": "Color space", - "ColorTransfer": "Color transfer", - "CommunityRating": "Community rating", - "Composer": "Composer", - "ConfigureDateAdded": "Configure how date added is determined in the Jellyfin Server dashboard under Library settings", - "ConfirmDeleteImage": "Delete image?", - "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?", - "ConfirmDeleteItems": "Deleting these items will delete them from both the file system and your media library. Are you sure you wish to continue?", - "ConfirmDeletion": "Confirm Deletion", - "ConfirmEndPlayerSession": "Would you like to shutdown Jellyfin on {0}?", - "Connect": "Connect", - "ContinueWatching": "Continue watching", - "Continuing": "Continuing", - "CopyStreamURL": "Copy Stream URL", - "CopyStreamURLSuccess": "URL copied successfully.", - "CopyStreamURLError": "There was an error copying the URL.", - "CriticRating": "Critic rating", - "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.", - "DateAdded": "Date added", - "DatePlayed": "Date played", - "DeathDateValue": "Died: {0}", - "Default": "Default", - "DefaultErrorMessage": "There was an error processing the request. Please try again later.", - "DefaultMetadataLangaugeDescription": "These are your defaults and can be customized on a per-library basis.", - "DefaultSubtitlesHelp": "Subtitles are loaded based on the default and forced flags in the embedded metadata. Language preferences are considered when multiple options are available.", - "DeinterlaceMethodHelp": "Select the deinterlacing method to use when transcoding interlaced content.", - "Delete": "Delete", - "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", - "DeleteImage": "Delete Image", - "DeleteImageConfirmation": "Are you sure you wish to delete this image?", - "DeleteMedia": "Delete media", - "DeleteUser": "Delete User", - "DeleteUserConfirmation": "Are you sure you wish to delete this user?", - "Depressed": "Depressed", - "Descending": "Descending", - "Desktop": "Desktop", - "DetectingDevices": "Detecting devices", - "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", - "DirectPlaying": "Direct playing", - "DirectStreamHelp1": "The media is compatible with the device regarding resolution and media type (H.264, AC3, etc), but is in an incompatible file container (mkv, avi, wmv, etc). The video will be re-packaged on the fly before streaming it to the device.", - "DirectStreamHelp2": "Direct Streaming a file uses very little processing power without any loss in video quality.", - "DirectStreaming": "Direct streaming", - "Director": "Director", - "Directors": "Directors", - "Disabled": "Disabled", - "Disc": "Disc", - "Disconnect": "Disconnect", - "Dislike": "Dislike", - "Display": "Display", - "DisplayInMyMedia": "Display on home screen", - "DisplayInOtherHomeScreenSections": "Display in home screen sections such as latest media and continue watching", - "DisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", - "DisplayMissingEpisodesWithinSeasonsHelp": "This must also be enabled for TV libraries in the server configuration.", - "DisplayModeHelp": "Select the layout style you want for the interface.", - "DoNotRecord": "Do not record", - "Down": "Down", - "Download": "Download", - "DownloadsValue": "{0} downloads", - "DrmChannelsNotImported": "Channels with DRM will not be imported.", - "DropShadow": "Drop Shadow", - "EasyPasswordHelp": "Your easy pin code is used for offline access on supported clients and can also be used for easy in-network sign in.", - "Edit": "Edit", - "EditImages": "Edit images", - "EditMetadata": "Edit metadata", - "EditSubtitles": "Edit subtitles", - "EnableBackdrops": "Backdrops", - "EnableBackdropsHelp": "Display backdrops in the background of some pages while browsing the library.", - "EnableCinemaMode": "Cinema mode", - "EnableColorCodedBackgrounds": "Color coded backgrounds", - "EnableDecodingColorDepth10Hevc": "Enable 10-Bit hardware decoding for HEVC", - "EnableDecodingColorDepth10Vp9": "Enable 10-Bit hardware decoding for VP9", - "EnableDisplayMirroring": "Display mirroring", - "EnableExternalVideoPlayers": "External video players", - "EnableExternalVideoPlayersHelp": "An external player menu will be shown when starting video playback.", - "EnableHardwareEncoding": "Enable hardware encoding", - "EnableNextVideoInfoOverlay": "Show next video info during playback", - "EnableNextVideoInfoOverlayHelp": "At the end of a video, display info about the next video coming up in the current playlist.", - "EnablePhotos": "Display photos", - "EnablePhotosHelp": "Images will be detected and displayed alongside other media files.", - "EnableStreamLooping": "Auto-loop live streams", - "EnableStreamLoopingHelp": "Enable this if live streams only contain a few seconds of data and need to be continuously requested. Enabling this when not needed may cause problems.", - "EnableThemeSongs": "Theme songs", - "EnableThemeSongsHelp": "Play theme songs in the background while browsing the library.", - "EnableThemeVideos": "Theme videos", - "EnableThemeVideosHelp": "Play theme videos in the background while browsing the library.", - "EnableDetailsBanner": "Details Banner", - "EnableDetailsBannerHelp": "Display a banner image at the top of the item details page.", - "Ended": "Ended", - "EndsAtValue": "Ends at {0}", - "Episode": "Episode", - "Episodes": "Episodes", - "ErrorAddingListingsToSchedulesDirect": "There was an error adding the lineup to your Schedules Direct account. Schedules Direct only allows a limited number of lineups per account. You may need to log into the Schedules Direct website and remove others listings from your account before proceeding.", - "ErrorAddingMediaPathToVirtualFolder": "There was an error adding the media path. Please ensure the path is valid and the Jellyfin Server process has access to that location.", - "ErrorAddingTunerDevice": "There was an error adding the tuner device. Please ensure it is accessible and try again.", - "ErrorAddingXmlTvFile": "There was an error accessing the XMLTV file. Please ensure the file exists and try again.", - "ErrorDeletingItem": "There was an error deleting the item from Jellyfin Server. Please check that Jellyfin Server has write access to the media folder and try again.", - "ErrorGettingTvLineups": "There was an error downloading TV lineups. Please ensure your information is correct and try again.", - "ErrorMessageStartHourGreaterThanEnd": "End time must be greater than the start time.", - "ErrorPleaseSelectLineup": "Please select a lineup and try again. If no lineups are available, then please check that your username, password, and postal code is correct.", - "ErrorSavingTvProvider": "There was an error saving the TV provider. Please ensure it is accessible and try again.", - "EveryNDays": "Every {0} days", - "ExitFullscreen": "Exit full screen", - "ExtraLarge": "Extra Large", - "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, resource intensive, and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", - "Extras": "Extras", - "FFmpegSavePathNotFound": "We're unable to locate FFmpeg using the path you've entered. FFprobe is also required and must exist in the same folder. These components are normally bundled together in the same download. Please check the path and try again.", - "FastForward": "Fast-forward", - "Favorite": "Favorite", - "Favorites": "Favorites", - "Features": "Features", - "FetchingData": "Fetching additional data", - "File": "File", - "FileNotFound": "File not found.", - "FileReadCancelled": "The file read has been canceled.", - "FileReadError": "An error occurred while reading the file.", - "Filters": "Filters", - "FolderTypeBooks": "Books", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeMusicVideos": "Music Videos", - "FolderTypeTvShows": "TV Shows", - "FolderTypeUnset": "Mixed Content", - "Folders": "Folders", - "FormatValue": "Format: {0}", - "Friday": "Friday", - "Fullscreen": "Full screen", - "General": "General", - "Genre": "Genre", - "Genres": "Genres", - "GroupBySeries": "Group by series", - "GroupVersions": "Group versions", - "GuestStar": "Guest star", - "Guide": "Guide", - "GuideProviderLogin": "Login", - "GuideProviderSelectListings": "Select Listings", - "H264CrfHelp": "The Constant Rate Factor (CRF) is the default quality setting for the x264 encoder. You can set the values between 0 and 51, where lower values would result in better quality (at the expense of higher file sizes). Sane values are between 18 and 28. The default for x264 is 23, so you can use this as a starting point.", - "EncoderPresetHelp": "Choose a faster value to improve performance, or a slower value to improve quality.", - "HDPrograms": "HD programs", - "HardwareAccelerationWarning": "Enabling hardware acceleration may cause instability in some environments. Ensure that your operating system and video drivers are fully up to date. If you have difficulty playing video after enabling this, you'll need to change the setting back to None.", - "HeaderAccessSchedule": "Access Schedule", - "HeaderAccessScheduleHelp": "Create an access schedule to limit access to certain hours.", - "HeaderActiveDevices": "Active Devices", - "HeaderActiveRecordings": "Active Recordings", - "HeaderActivity": "Activity", - "HeaderAddScheduledTaskTrigger": "Add Trigger", - "HeaderAddToCollection": "Add to Collection", - "HeaderAddToPlaylist": "Add to Playlist", - "HeaderAddUpdateImage": "Add/Update Image", - "HeaderAddUser": "Add User", - "HeaderAdditionalParts": "Additional Parts", - "HeaderAdmin": "Admin", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderAlert": "Alert", - "HeaderAllowMediaDeletionFrom": "Allow Media Deletion From", - "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 a Jellyfin account, or by manually granting the application a key.", - "ApiKeysCaption": "List of the currently enabled API keys", - "HeaderApp": "App", - "HeaderAppearsOn": "Appears On", - "HeaderAudioBooks": "Audio Books", - "HeaderAudioSettings": "Audio Settings", - "HeaderAutomaticUpdates": "Automatic Updates", - "HeaderBlockItemsWithNoRating": "Block items with no or unrecognized rating information:", - "HeaderBooks": "Books", - "HeaderBranding": "Branding", - "HeaderCancelRecording": "Cancel Recording", - "HeaderCancelSeries": "Cancel Series", - "HeaderCastAndCrew": "Cast & Crew", - "HeaderCastCrew": "Cast & Crew", - "HeaderChannelAccess": "Channel Access", - "HeaderChannels": "Channels", - "HeaderChapterImages": "Chapter Images", - "HeaderCodecProfile": "Codec Profile", - "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.", - "HeaderConfigureRemoteAccess": "Configure Remote Access", - "HeaderConfirmPluginInstallation": "Confirm Plugin Installation", - "HeaderConfirmProfileDeletion": "Confirm Profile Deletion", - "HeaderConfirmRevokeApiKey": "Revoke API Key", - "HeaderConnectToServer": "Connect to Server", - "HeaderConnectionFailure": "Connection Failure", - "HeaderContainerProfile": "Container Profile", - "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.", - "HeaderContinueListening": "Continue Listening", - "HeaderContinueWatching": "Continue Watching", - "HeaderCustomDlnaProfiles": "Custom Profiles", - "HeaderDateIssued": "Date Issued", - "HeaderDefaultRecordingSettings": "Default Recording Settings", - "HeaderDeleteDevice": "Delete Device", - "HeaderDeleteItem": "Delete Item", - "HeaderDeleteItems": "Delete Items", - "HeaderDeleteProvider": "Delete Provider", - "HeaderDeleteTaskTrigger": "Delete Task Trigger", - "HeaderDetectMyDevices": "Detect My Devices", - "HeaderDeveloperInfo": "Developer Info", - "HeaderDeviceAccess": "Device Access", - "HeaderDevices": "Devices", - "HeaderDirectPlayProfile": "Direct Play Profile", - "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.", - "HeaderDisplay": "Display", - "HeaderDownloadSync": "Download & Sync", - "HeaderDVR": "DVR", - "HeaderEasyPinCode": "Easy Pin Code", - "HeaderEditImages": "Edit Images", - "HeaderEnabledFields": "Enabled Fields", - "HeaderEnabledFieldsHelp": "Uncheck a field to lock it and prevent its data from being changed.", - "HeaderEpisodes": "Episodes", - "HeaderError": "Error", - "HeaderExternalIds": "External IDs:", - "HeaderFavoriteBooks": "Favorite Books", - "HeaderFavoriteMovies": "Favorite Movies", - "HeaderFavoriteShows": "Favorite Shows", - "HeaderFavoriteEpisodes": "Favorite Episodes", - "HeaderFavoriteAlbums": "Favorite Albums", - "HeaderFavoritePeople": "Favorite People", - "HeaderFavoriteArtists": "Favorite Artists", - "HeaderFavoriteSongs": "Favorite Songs", - "HeaderFavoriteVideos": "Favorite Videos", - "HeaderFavoritePlaylists": "Favorite Playlists", - "HeaderFeatureAccess": "Feature Access", - "HeaderFeatures": "Features", - "HeaderFetchImages": "Fetch Images:", - "HeaderFetcherSettings": "Fetcher Settings", - "HeaderFilters": "Filters", - "HeaderForKids": "For Kids", - "HeaderForgotPassword": "Forgot Password", - "HeaderFrequentlyPlayed": "Frequently Played", - "HeaderGenres": "Genres", - "HeaderGuideProviders": "TV Guide Data Providers", - "HeaderHome": "Home", - "HeaderHttpHeaders": "HTTP Headers", - "HeaderHttpsSettings": "HTTPS Settings", - "HeaderIdentification": "Identification", - "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.", - "HeaderIdentificationHeader": "Identification Header", - "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.", - "HeaderImageOptions": "Image Options", - "HeaderImageSettings": "Image Settings", - "HeaderInstall": "Install", - "HeaderInstantMix": "Instant Mix", - "HeaderItems": "Items", - "HeaderKeepRecording": "Keep Recording", - "HeaderKeepSeries": "Keep Series", - "HeaderKodiMetadataHelp": "To enable or disable NFO metadata, edit a library in Jellyfin library setup and locate the metadata savers section.", - "HeaderLatestEpisodes": "Latest Episodes", - "HeaderLatestMedia": "Latest Media", - "HeaderLatestMovies": "Latest Movies", - "HeaderLatestMusic": "Latest Music", - "HeaderLatestRecordings": "Latest Recordings", - "HeaderLibraries": "Libraries", - "HeaderLibraryAccess": "Library Access", - "HeaderLibraryFolders": "Library Folders", - "HeaderLibraryOrder": "Library Order", - "HeaderLibrarySettings": "Library Settings", - "HeaderLiveTV": "Live TV", - "HeaderLiveTv": "Live TV", - "HeaderLiveTvTunerSetup": "Live TV Tuner Setup", - "HeaderLoginFailure": "Login Failure", - "HeaderMedia": "Media", - "HeaderMediaFolders": "Media Folders", - "HeaderMediaInfo": "Media Info", - "HeaderMetadataSettings": "Metadata Settings", - "HeaderMoreLikeThis": "More Like This", - "HeaderMovies": "Movies", - "HeaderMusicQuality": "Music Quality", - "HeaderMusicVideos": "Music Videos", - "HeaderMyDevice": "My Device", - "HeaderMyMedia": "My Media", - "HeaderMyMediaSmall": "My Media (small)", - "HeaderNavigation": "Navigation", - "HeaderNewApiKey": "New API Key", - "HeaderNewDevices": "New Devices", - "HeaderNextEpisodePlayingInValue": "Next Episode Playing in {0}", - "HeaderNextUp": "Next Up", - "HeaderNextVideoPlayingInValue": "Next Video Playing in {0}", - "HeaderOnNow": "On Now", - "HeaderOtherItems": "Other Items", - "HeaderParentalRatings": "Parental Ratings", - "HeaderPassword": "Password", - "HeaderPasswordReset": "Password Reset", - "HeaderPaths": "Paths", - "HeaderPendingInvitations": "Pending Invitations", - "HeaderPeople": "People", - "HeaderPhotoAlbums": "Photo Albums", - "HeaderPinCodeReset": "Reset Pin Code", - "HeaderPlayAll": "Play All", - "HeaderPlayOn": "Play On", - "HeaderPlayback": "Media Playback", - "HeaderPlaybackError": "Playback Error", - "HeaderPleaseSignIn": "Please sign in", - "HeaderPluginInstallation": "Plugin Installation", - "HeaderPreferredMetadataLanguage": "Preferred Metadata Language", - "HeaderProfile": "Profile", - "HeaderProfileInformation": "Profile Information", - "HeaderProfileServerSettingsHelp": "These values control how Jellyfin Server will present itself to the device.", - "HeaderRecentlyPlayed": "Recently Played", - "HeaderRecordingOptions": "Recording Options", - "HeaderRecordingPostProcessing": "Recording Post Processing", - "HeaderRemoteAccessSettings": "Remote Access Settings", - "HeaderRemoteControl": "Remote Control", - "HeaderRemoveMediaFolder": "Remove Media Folder", - "HeaderRemoveMediaLocation": "Remove Media Location", - "HeaderResponseProfile": "Response Profile", - "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.", - "HeaderRestart": "Restart", - "HeaderRevisionHistory": "Revision History", - "HeaderRunningTasks": "Running Tasks", - "HeaderScenes": "Scenes", - "HeaderSchedule": "Schedule", - "HeaderSeasons": "Seasons", - "HeaderSecondsValue": "{0} Seconds", - "HeaderSelectCertificatePath": "Select Certificate Path", - "HeaderSelectMetadataPath": "Select Metadata Path", - "HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.", - "HeaderSelectPath": "Select Path", - "HeaderSelectServer": "Select Server", - "HeaderSelectServerCachePath": "Select Server Cache Path", - "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.", - "HeaderSelectTranscodingPath": "Select Transcoding Temporary Path", - "HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.", - "HeaderSendMessage": "Send Message", - "HeaderSeries": "Series", - "HeaderSeriesOptions": "Series Options", - "HeaderSeriesStatus": "Series Status", - "HeaderServerAddressSettings": "Server Address Settings", - "HeaderServerSettings": "Server Settings", - "HeaderSettings": "Settings", - "HeaderSetupLibrary": "Setup your media libraries", - "HeaderShutdown": "Shutdown", - "HeaderSortBy": "Sort By", - "HeaderSortOrder": "Sort Order", - "HeaderSpecialEpisodeInfo": "Special Episode Info", - "HeaderSpecialFeatures": "Special Features", - "HeaderStartNow": "Start Now", - "HeaderStatus": "Status", - "HeaderStopRecording": "Stop Recording", - "HeaderSubtitleAppearance": "Subtitle Appearance", - "HeaderSubtitleDownloads": "Subtitle Downloads", - "HeaderSubtitleProfile": "Subtitle Profile", - "HeaderSubtitleProfiles": "Subtitle Profiles", - "HeaderSubtitleProfilesHelp": "Subtitle profiles describe the subtitle formats supported by the device.", - "HeaderSyncPlaySelectGroup": "Join a group", - "HeaderSyncPlayEnabled": "SyncPlay enabled", - "HeaderSystemDlnaProfiles": "System Profiles", - "HeaderTags": "Tags", - "HeaderTaskTriggers": "Task Triggers", - "HeaderThisUserIsCurrentlyDisabled": "This user is currently disabled", - "HeaderTracks": "Tracks", - "HeaderTranscodingProfile": "Transcoding Profile", - "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.", - "HeaderTunerDevices": "Tuner Devices", - "HeaderTuners": "Tuners", - "HeaderTypeImageFetchers": "{0} Image Fetchers", - "HeaderTypeText": "Enter Text", - "HeaderUpcomingOnTV": "Upcoming On TV", - "HeaderUploadImage": "Upload Image", - "HeaderUser": "User", - "HeaderUsers": "Users", - "HeaderVideoQuality": "Video Quality", - "HeaderVideoType": "Video Type", - "HeaderVideoTypes": "Video Types", - "HeaderVideos": "Videos", - "HeaderXmlDocumentAttribute": "Xml Document Attribute", - "HeaderXmlDocumentAttributes": "Xml Document Attributes", - "HeaderXmlSettings": "Xml Settings", - "HeaderYears": "Years", - "HeadersFolders": "Folders", - "Help": "Help", - "Hide": "Hide", - "HideWatchedContentFromLatestMedia": "Hide watched content from latest media", - "Home": "Home", - "Horizontal": "Horizontal", - "HttpsRequiresCert": "To enable secure connections, you will need to supply a trusted SSL certificate, such as Let's Encrypt. Please either supply a certificate, or disable secure connections.", - "Identify": "Identify", - "Images": "Images", - "ImportFavoriteChannelsHelp": "If enabled, only channels that are marked as favorite on the tuner device will be imported.", - "ImportMissingEpisodesHelp": "If enabled, information about missing episodes will be imported into your Jellyfin database and displayed within seasons and series. This may cause significantly longer library scans.", - "InstallingPackage": "Installing {0} (version {1})", - "InstantMix": "Instant mix", - "ItemCount": "{0} items", - "Items": "Items", - "Kids": "Kids", - "Label3DFormat": "3D format:", - "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", - "LabelAccessDay": "Day of week:", - "LabelAccessEnd": "End time:", - "LabelAccessStart": "Start time:", - "LabelAirDays": "Air days:", - "LabelAirTime": "Air time:", - "LabelAirsAfterSeason": "Airs after season:", - "LabelAirsBeforeEpisode": "Airs before episode:", - "LabelAirsBeforeSeason": "Airs before season:", - "LabelAlbum": "Album:", - "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some devices require a specific value, regardless of the size of the image.", - "LabelAlbumArtMaxHeight": "Album art max height:", - "LabelAlbumArtMaxHeightHelp": "Max resolution of album art exposed via upnp:albumArtURI.", - "LabelAlbumArtMaxWidth": "Album art max width:", - "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.", - "LabelAlbumArtPN": "Album art PN:", - "LabelAlbumArtists": "Album artists:", - "LabelAll": "All", - "LabelAllowHWTranscoding": "Allow hardware transcoding", - "LabelAllowServerAutoRestart": "Allow the server to restart automatically to apply updates", - "LabelAllowServerAutoRestartHelp": "The server will only restart during idle periods when no users are active.", - "LabelAllowedRemoteAddresses": "Remote IP address filter:", - "LabelAllowedRemoteAddressesMode": "Remote IP address filter mode:", - "LabelAppName": "App name", - "LabelAppNameExample": "Example: Sickbeard, Sonarr", - "LabelArtists": "Artists:", - "LabelArtistsHelp": "Separate multiple using ;", - "LabelAudio": "Audio", - "LabelAudioBitDepth": "Audio bit depth:", - "LabelAudioBitrate": "Audio bitrate:", - "LabelAudioChannels": "Audio channels:", - "LabelAudioCodec": "Audio codec:", - "LabelAudioLanguagePreference": "Preferred audio language:", - "LabelAudioSampleRate": "Audio sample rate:", - "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.", - "LabelBirthDate": "Birth date:", - "LabelBirthYear": "Birth year:", - "LabelBitrate": "Bitrate:", - "LabelBlastMessageInterval": "Alive message interval (seconds)", - "LabelBlastMessageIntervalHelp": "Determines the duration in seconds between blast alive messages.", - "LabelBlockContentWithTags": "Block items with tags:", - "LabelBurnSubtitles": "Burn subtitles:", - "LabelCache": "Cache:", - "LabelCachePath": "Cache path:", - "LabelCachePathHelp": "Specify a custom location for server cache files such as images. Leave blank to use the server default.", - "LabelCancelled": "Cancelled", - "LabelCertificatePassword": "Certificate password:", - "LabelCertificatePasswordHelp": "If your certificate requires a password, please enter it here.", - "LabelChannels": "Channels:", - "LabelCollection": "Collection:", - "LabelCommunityRating": "Community rating:", - "LabelContentType": "Content type:", - "LabelCorruptedFrames": "Corrupted frames:", - "LabelCountry": "Country:", - "LabelCriticRating": "Critic rating:", - "LabelCurrentPassword": "Current password:", - "LabelCustomCertificatePath": "Custom SSL certificate path:", - "LabelCustomCertificatePathHelp": "Path to a PKCS #12 file containing a certificate and private key to enable TLS support on a custom domain.", - "LabelCustomCss": "Custom CSS:", - "LabelCustomCssHelp": "Apply your own custom styling to the web interface.", - "LabelCustomDeviceDisplayName": "Display name:", - "LabelCustomDeviceDisplayNameHelp": "Supply a custom display name or leave empty to use the name reported by the device.", - "LabelCustomRating": "Custom rating:", - "LabelDashboardTheme": "Server dashboard theme:", - "LabelDateAdded": "Date added:", - "LabelDateAddedBehavior": "Date added behavior for new content:", - "LabelDateAddedBehaviorHelp": "If a metadata value is present it will always be used before either of these options.", - "LabelDateTimeLocale": "Date time locale:", - "LabelDay": "Day:", - "LabelDeathDate": "Death date:", - "LabelDefaultScreen": "Default screen:", - "LabelDefaultUser": "Default user:", - "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.", - "LabelDeinterlaceMethod": "Deinterlacing method:", - "LabelDeviceDescription": "Device description", - "LabelDidlMode": "DIDL mode:", - "LabelDiscNumber": "Disc number:", - "LabelDisplayLanguage": "Display language:", - "LabelDisplayLanguageHelp": "Translating Jellyfin is an ongoing project.", - "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", - "LabelDisplayMode": "Display mode:", - "LabelDisplayName": "Display name:", - "LabelDisplayOrder": "Display order:", - "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in", - "LabelDownMixAudioScale": "Audio boost when downmixing:", - "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. A value of one will preserve the original volume.", - "LabelDownloadLanguages": "Download languages:", - "LabelDropImageHere": "Drop image here, or click to browse.", - "LabelDroppedFrames": "Dropped frames:", - "LabelDropShadow": "Drop shadow:", - "LabelDynamicExternalId": "{0} Id:", - "LabelEasyPinCode": "Easy pin code:", - "LabelEmbedAlbumArtDidl": "Embed album art in Didl", - "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.", - "LabelEnableAutomaticPortMap": "Enable automatic port mapping", - "LabelEnableAutomaticPortMapHelp": "Automatically forward public ports on your router to local ports on your server via UPnP. This may not work with some router models or network configurations. Changes will not apply until after a server restart.", - "LabelEnableBlastAliveMessages": "Blast alive messages", - "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.", - "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval (seconds)", - "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches performed by Jellyfin.", - "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging", - "LabelEnableDlnaDebugLoggingHelp": "Create large log files and should only be used as needed for troubleshooting purposes.", - "LabelEnableDlnaPlayTo": "Enable DLNA Play To", - "LabelEnableDlnaPlayToHelp": "Detect devices within your network and offer the ability to remote control them.", - "LabelEnableDlnaServer": "Enable DLNA server", - "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play content.", - "LabelEnableHardwareDecodingFor": "Enable hardware decoding for:", - "LabelEnableHttps": "Enable HTTPS", - "LabelEnableHttpsHelp": "Enables the server to listen on the configured HTTPS port. A valid certificate must also be configured in order for this to take effect.", - "LabelEnableRealtimeMonitor": "Enable real time monitoring", - "LabelEnableRealtimeMonitorHelp": "Changes to files will be processed immediately, on supported file systems.", - "LabelEnableSingleImageInDidlLimit": "Limit to single embedded image", - "LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.", - "LabelEndDate": "End date:", - "LabelEpisodeNumber": "Episode number:", - "LabelEvent": "Event:", - "LabelEveryXMinutes": "Every:", - "LabelBaseUrl": "Base URL:", - "LabelBaseUrlHelp": "Adds a custom subdirectory to the server URL. For example: http://example.com/<baseurl>", - "LabelExtractChaptersDuringLibraryScan": "Extract chapter images during the library scan", - "LabelExtractChaptersDuringLibraryScanHelp": "Generate chapter images when videos are imported during the library scan. Otherwise, they will be extracted during the chapter images scheduled task, allowing the regular library scan to complete faster.", - "LabelFailed": "Failed", - "LabelFileOrUrl": "File or URL:", - "LabelFinish": "Finish", - "LabelFolder": "Folder:", - "LabelFont": "Font:", - "LabelForgotPasswordUsernameHelp": "Enter your username, if you remember it.", - "LabelFormat": "Format:", - "LabelFriendlyName": "Friendly name:", - "LabelServerNameHelp": "This name will be used to identify the server and will default to the server's computer name.", - "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:", - "LabelEncoderPreset": "H264 and H265 encoding preset:", - "LabelHardwareAccelerationType": "Hardware acceleration:", - "LabelHardwareAccelerationTypeHelp": "Hardware acceleration requires additional configuration.", - "LabelHomeNetworkQuality": "Home network quality:", - "LabelHomeScreenSectionValue": "Home screen section {0}:", - "LabelHttpsPort": "Local HTTPS port number:", - "LabelHttpsPortHelp": "The TCP port number that Jellyfin's HTTPS server should bind to.", - "LabelIconMaxHeight": "Icon maximum height:", - "LabelIconMaxHeightHelp": "Maximum resolution of icons exposed via upnp:icon.", - "LabelIconMaxWidth": "Icon maximum width:", - "LabelIconMaxWidthHelp": "Maximum resolution of icons exposed via upnp:icon.", - "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.", - "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.", - "LabelImageType": "Image type:", - "LabelImportOnlyFavoriteChannels": "Restrict to channels marked as favorite", - "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", - "LabelInNetworkSignInWithEasyPasswordHelp": "Use the easy pin code to sign in to clients within your local network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", - "LabelInternetQuality": "Internet quality:", - "LabelKeepUpTo": "Keep up to:", - "LabelKidsCategories": "Children's categories:", - "LabelKodiMetadataDateFormat": "Release date format:", - "LabelKodiMetadataDateFormatHelp": "All dates within NFO files will be parsed using this format.", - "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart to extrathumbs field", - "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", - "LabelKodiMetadataEnablePathSubstitution": "Enable path substitution", - "LabelKodiMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.", - "LabelKodiMetadataSaveImagePaths": "Save image paths within nfo files", - "LabelKodiMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Kodi guidelines.", - "LabelKodiMetadataUser": "Save user watch data to NFO files for:", - "LabelKodiMetadataUserHelp": "Save watch data to NFO files for other applications to utilize.", - "LabelLanNetworks": "LAN networks:", - "LabelLanguage": "Language:", - "LabelLibraryPageSize": "Library page size:", - "LabelLibraryPageSizeHelp": "Sets the amount of items to show on a library page. Set to 0 in order to disable paging.", - "LabelLineup": "Lineup:", - "LabelLocalHttpServerPortNumber": "Local HTTP port number:", - "LabelLocalHttpServerPortNumberHelp": "The TCP port number that Jellyfin's HTTP server should bind to.", - "LabelLockItemToPreventChanges": "Lock this item to prevent future changes", - "LabelLoginDisclaimer": "Login disclaimer:", - "LabelLoginDisclaimerHelp": "A message that will be displayed at the bottom of the login page.", - "LabelLogs": "Logs:", - "LabelManufacturer": "Manufacturer:", - "LabelManufacturerUrl": "Manufacturer URL", - "LabelMatchType": "Match type:", - "LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:", - "LabelMaxChromecastBitrate": "Chromecast streaming quality:", - "LabelMaxParentalRating": "Maximum allowed parental rating:", - "LabelMaxResumePercentage": "Maximum resume percentage:", - "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time.", - "LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:", - "LabelMaxStreamingBitrate": "Maximum streaming quality:", - "LabelMaxStreamingBitrateHelp": "Specify a maximum bitrate when streaming.", - "LabelMessageText": "Message text:", - "LabelMessageTitle": "Message title:", - "LabelMetadata": "Metadata:", - "LabelMetadataDownloadLanguage": "Preferred download language:", - "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.", - "LabelMetadataReaders": "Metadata readers:", - "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.", - "LabelMetadataSavers": "Metadata savers:", - "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.", - "LabelMethod": "Method:", - "LabelMinBackdropDownloadWidth": "Minimum backdrop download width:", - "LabelMinResumeDuration": "Minimum resume duration:", - "LabelMinResumeDurationHelp": "The shortest video length in seconds that will save playback location and let you resume.", - "LabelMinResumePercentage": "Minimum resume percentage:", - "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time.", - "LabelMinScreenshotDownloadWidth": "Minimum screenshot download width:", - "LabelModelDescription": "Model description", - "LabelModelName": "Model name", - "LabelModelNumber": "Model number", - "LabelModelUrl": "Model URL", - "LabelMonitorUsers": "Monitor activity from:", - "LabelMovieCategories": "Movie categories:", - "LabelMoviePrefix": "Movie prefix:", - "LabelMoviePrefixHelp": "If a prefix is applied to movie titles, enter it here so the server can handle it properly.", - "LabelMovieRecordingPath": "Movie recording path (optional):", - "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:", - "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music.", - "LabelName": "Name:", - "LabelChromecastVersion": "Chromecast Version", - "LabelStable": "Stable", - "LabelNightly": "Nightly", - "LabelNewName": "New name:", - "LabelNewPassword": "New password:", - "LabelNewPasswordConfirm": "New password confirm:", - "LabelNewsCategories": "News categories:", - "LabelNext": "Next", - "LabelNotificationEnabled": "Enable this notification", - "LabelNumber": "Number:", - "LabelNumberOfGuideDays": "Number of days of guide data to download:", - "LabelNumberOfGuideDaysHelp": "Downloading more days worth of guide data provides the ability to schedule out further in advance and view more listings, but it will also take longer to download. Auto will choose based on the number of channels.", - "LabelOptionalNetworkPath": "(Optional) Shared network folder:", - "LabelOptionalNetworkPathHelp": "If this folder is shared on your network, supplying the network share path can allow Jellyfin apps on other devices to access media files directly. For example, {0} or {1}.", - "LabelOriginalAspectRatio": "Original aspect ratio:", - "LabelOriginalTitle": "Original title:", - "LabelOverview": "Overview:", - "LabelParentNumber": "Parent number:", - "LabelParentalRating": "Parental rating:", - "LabelPassword": "Password:", - "LabelPasswordConfirm": "Password (confirm):", - "LabelPasswordResetProvider": "Password Reset Provider:", - "LabelPasswordRecoveryPinCode": "Pin code:", - "LabelPath": "Path:", - "LabelPersonRole": "Role:", - "LabelPersonRoleHelp": "Example: Ice cream truck driver", - "LabelPlaceOfBirth": "Place of birth:", - "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language", - "LabelPlayer": "Player:", - "LabelPlayerDimensions": "Player dimensions:", - "LabelPlaylist": "Playlist:", - "LabelPlayMethod": "Play method:", - "LabelPleaseRestart": "Changes will take effect after manually reloading the web client.", - "LabelPostProcessor": "Post-processing application:", - "LabelPostProcessorArguments": "Post-processor command line arguments:", - "LabelPostProcessorArgumentsHelp": "Use {path} as the path to the recording file.", - "LabelPreferredDisplayLanguage": "Preferred display language:", - "LabelPreferredDisplayLanguageHelp": "Translating Jellyfin is an ongoing project.", - "LabelPreferredSubtitleLanguage": "Preferred subtitle language:", - "LabelPrevious": "Previous", - "LabelProfileAudioCodecs": "Audio codecs:", - "LabelProfileCodecs": "Codecs:", - "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.", - "LabelProfileContainer": "Container:", - "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.", - "LabelProfileVideoCodecs": "Video codecs:", - "LabelProtocol": "Protocol:", - "LabelProtocolInfo": "Protocol info:", - "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "LabelPublicHttpPort": "Public HTTP port number:", - "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local HTTP port.", - "LabelPublicHttpsPort": "Public HTTPS port number:", - "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local HTTPS port.", - "LabelReadHowYouCanContribute": "Learn how you can contribute.", - "LabelReasonForTranscoding": "Reason for transcoding:", - "LabelRecord": "Record:", - "LabelRecordingPath": "Default recording path:", - "LabelRecordingPathHelp": "Specify the default location to save recordings. If left empty, the server's program data folder will be used.", - "LabelRefreshMode": "Refresh mode:", - "LabelReleaseDate": "Release date:", - "LabelRemoteClientBitrateLimit": "Internet streaming bitrate limit (Mbps):", - "LabelRemoteClientBitrateLimitHelp": "An optional per-stream bitrate limit for all out of network devices. This is useful to prevent devices from requesting a higher bitrate than your internet connection can handle. This may result in increased CPU load on your server in order to transcode videos on the fly to a lower bitrate.", - "LabelRequireHttps": "Require HTTPS", - "LabelRequireHttpsHelp": "If checked, the server will automatically redirect all requests over HTTP to HTTPS. This has no effect if the server is not listening on HTTPS.", - "LabelRuntimeMinutes": "Run time (minutes):", - "LabelSaveLocalMetadata": "Save artwork into media folders", - "LabelSaveLocalMetadataHelp": "Saving artwork into media folders will put them in a place where they can be easily edited.", - "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", - "LabelScreensaver": "Screensaver:", - "EnableFasterAnimations": "Faster animations", - "EnableFasterAnimationsHelp": "Use faster animations and transitions", - "LabelSeasonNumber": "Season number:", - "LabelSelectFolderGroups": "Automatically group content from the following folders into views such as Movies, Music and TV:", - "LabelSelectFolderGroupsHelp": "Folders that are unchecked will be displayed by themselves in their own view.", - "LabelSelectUsers": "Select users:", - "LabelSelectVersionToInstall": "Select version to install:", - "LabelSendNotificationToUsers": "Send the notification to:", - "LabelSerialNumber": "Serial number", - "LabelSeriesRecordingPath": "Series recording path (optional):", - "LabelServerHost": "Host:", - "LabelServerHostHelp": "192.168.1.100:8096 or https://myserver.com", - "LabelServerName": "Server name:", - "LabelSimultaneousConnectionLimit": "Simultaneous stream limit:", - "LabelSize": "Size:", - "LabelSkin": "Skin:", - "LabelSkipBackLength": "Skip back length:", - "LabelSkipForwardLength": "Skip forward length:", - "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language", - "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.", - "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains embedded subtitles", - "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery and decrease the likelihood of video transcoding.", - "LabelSonyAggregationFlags": "Sony aggregation flags:", - "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.", - "LabelSortBy": "Sort by:", - "LabelSortOrder": "Sort order:", - "LabelSortTitle": "Sort title:", - "LabelSoundEffects": "Sound effects:", - "LabelSource": "Source:", - "LabelSpecialSeasonsDisplayName": "Special season display name:", - "LabelSportsCategories": "Sports categories:", - "LabelStartWhenPossible": "Start when possible:", - "LabelStatus": "Status:", - "LabelStopWhenPossible": "Stop when possible:", - "LabelStopping": "Stopping", - "LabelStreamType": "Stream type:", - "LabelSubtitleDownloaders": "Subtitle downloaders:", - "LabelSubtitleFormatHelp": "Example: srt", - "LabelSubtitlePlaybackMode": "Subtitle mode:", - "LabelSubtitles": "Subtitles", - "LabelSupportedMediaTypes": "Supported Media Types:", - "LabelSyncPlayTimeOffset": "Time offset with the server:", - "MillisecondsUnit": "ms", - "LabelSyncPlayPlaybackDiff": "Playback time difference:", - "LabelSyncPlaySyncMethod": "Sync method:", - "LabelSyncPlayNewGroup": "New group", - "LabelSyncPlayNewGroupDescription": "Create a new group", - "LabelSyncPlayLeaveGroup": "Leave group", - "LabelSyncPlayLeaveGroupDescription": "Disable SyncPlay", - "LabelSyncPlayAccessCreateAndJoinGroups": "Allow user to create and join groups", - "LabelSyncPlayAccessJoinGroups": "Allow user to join groups", - "LabelSyncPlayAccessNone": "Disabled for this user", - "LabelSyncPlayAccess": "SyncPlay access", - "LabelTVHomeScreen": "TV mode home screen:", - "LabelTag": "Tag:", - "LabelTagline": "Tagline:", - "LabelTextBackgroundColor": "Text background color:", - "LabelTextColor": "Text color:", - "LabelTextSize": "Text size:", - "LabelTheme": "Theme:", - "LabelTime": "Time:", - "LabelTimeLimitHours": "Time limit (hours):", - "LabelTitle": "Title:", - "LabelTrackNumber": "Track number:", - "LabelTranscodingAudioCodec": "Audio codec:", - "LabelTranscodingContainer": "Container:", - "LabelTranscodePath": "Transcode path:", - "LabelTranscodingTempPathHelp": "Specify a custom path for the transcode files served to clients. Leave blank to use the server default.", - "LabelTranscodes": "Transcodes:", - "LabelTranscodingFramerate": "Transcoding framerate:", - "LabelTranscodingProgress": "Transcoding progress:", - "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:", - "LabelTriggerType": "Trigger Type:", - "LabelTunerIpAddress": "Tuner IP Address:", - "LabelTunerType": "Tuner type:", - "LabelType": "Type:", - "LabelTypeMetadataDownloaders": "{0} metadata downloaders:", - "LabelTypeText": "Text", - "LabelUseNotificationServices": "Use the following services:", - "LabelUser": "User:", - "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 login attempts before user is locked out:", - "LabelUserRemoteClientBitrateLimitHelp": "Override the default global value set in server playback settings.", - "LabelUsername": "Username:", - "LabelVaapiDevice": "VA API Device:", - "LabelVaapiDeviceHelp": "This is the render node that is used for hardware acceleration.", - "LabelValue": "Value:", - "LabelVersion": "Version:", - "LabelVersionInstalled": "{0} installed", - "DashboardVersionNumber": "Version: {0}", - "DashboardServerName": "Server: {0}", - "DashboardOperatingSystem": "Operating System: {0}", - "DashboardArchitecture": "Architecture: {0}", - "LabelVideo": "Video", - "LabelVideoBitrate": "Video bitrate:", - "LabelVideoCodec": "Video codec:", - "LabelVideoResolution": "Video resolution:", - "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:", - "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.", - "LabelYear": "Year:", - "LabelYourFirstName": "Your first name:", - "LabelYoureDone": "You're Done!", - "LabelZipCode": "Zip Code:", - "LabelffmpegPath": "FFmpeg path:", - "LabelffmpegPathHelp": "The path to the ffmpeg application file, or folder containing ffmpeg.", - "LanNetworksHelp": "Comma separated list of IP addresses or IP/netmask entries for networks that will be considered on local network when enforcing bandwidth restrictions. If set, all other IP addresses will be considered to be on the external network and will be subject to the external bandwidth restrictions. If left blank, only the server's subnet is considered to be on the local network.", - "Large": "Large", - "LatestFromLibrary": "Latest {0}", - "LaunchWebAppOnStartup": "Launch the web interface when starting the server", - "LaunchWebAppOnStartupHelp": "Open the web client in your default web browser when the server initially starts. This will not occur when using the restart server function.", - "LearnHowYouCanContribute": "Learn how you can contribute.", - "LeaveBlankToNotSetAPassword": "You can leave this field blank to set no password.", - "LibraryAccessHelp": "Select the libraries to share with this user. Administrators will be able to edit all folders using the metadata manager.", - "Like": "Like", - "LinksValue": "Links: {0}", - "List": "List", - "Live": "Live", - "LiveBroadcasts": "Live broadcasts", - "LiveTV": "Live TV", - "Logo": "Logo", - "ManageLibrary": "Manage library", - "ManageRecording": "Manage recording", - "MapChannels": "Map Channels", - "MarkPlayed": "Mark played", - "MarkUnplayed": "Mark unplayed", - "MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.", - "MediaInfoAnamorphic": "Anamorphic", - "MediaInfoAspectRatio": "Aspect ratio", - "MediaInfoBitDepth": "Bit depth", - "MediaInfoBitrate": "Bitrate", - "MediaInfoChannels": "Channels", - "MediaInfoCodec": "Codec", - "MediaInfoCodecTag": "Codec tag", - "MediaInfoContainer": "Container", - "MediaInfoDefault": "Default", - "MediaInfoExternal": "External", - "MediaInfoForced": "Forced", - "MediaInfoFramerate": "Framerate", - "MediaInfoInterlaced": "Interlaced", - "MediaInfoLanguage": "Language", - "MediaInfoLayout": "Layout", - "MediaInfoLevel": "Level", - "MediaInfoPath": "Path", - "MediaInfoPixelFormat": "Pixel format", - "MediaInfoProfile": "Profile", - "MediaInfoRefFrames": "Ref frames", - "MediaInfoResolution": "Resolution", - "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.", - "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?", - "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?", - "MessageConfirmAppExit": "Do you want to exit?", - "MessageConfirmDeleteGuideProvider": "Are you sure you wish to delete this guide provider?", - "MessageConfirmDeleteTunerDevice": "Are you sure you wish to delete this device?", - "MessageConfirmProfileDeletion": "Are you sure you wish to delete this profile?", - "MessageConfirmRecordingCancellation": "Cancel recording?", - "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?", - "MessageConfirmRestart": "Are you sure you wish to restart Jellyfin Server?", - "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 the server?", - "MessageContactAdminToResetPassword": "Please contact your system administrator to reset your password.", - "MessageCreateAccountAt": "Create an account at {0}", - "MessageDeleteTaskTrigger": "Are you sure you wish to delete this task trigger?", - "MessageDirectoryPickerBSDInstruction": "For BSD, you may need to configure storage within your FreeNAS Jail in order to allow Jellyfin to access it.", - "MessageDirectoryPickerLinuxInstruction": "For Linux on Arch Linux, CentOS, Debian, Fedora, openSUSE, or Ubuntu, you must grant the service user at least read access to your storage locations.", - "MessageDownloadQueued": "Download queued.", - "MessageEnablingOptionLongerScans": "Enabling this option may result in significantly longer library scans.", - "MessageFileReadError": "There was an error reading the file. Please try again.", - "MessageForgotPasswordFileCreated": "The following file has been created on your server and contains instructions on how to proceed:", - "MessageForgotPasswordInNetworkRequired": "Please try again within your home network to initiate the password reset process.", - "MessageImageFileTypeAllowed": "Only JPEG and PNG files are supported.", - "MessageImageTypeNotSelected": "Please select an image type from the drop-down menu.", - "MessageInstallPluginFromApp": "This plugin must be installed from within the app you intend to use it in.", - "MessageInvalidForgotPasswordPin": "An invalid or expired pin code was entered. Please try again.", - "MessageInvalidUser": "Invalid username or password. Please try again.", - "MessageUnauthorizedUser": "You are not authorized to access the server at this time. Please contact your server administrator for more information.", - "MessageItemSaved": "Item saved.", - "MessageItemsAdded": "Items added.", - "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item or the global default value.", - "MessageNoAvailablePlugins": "No available plugins.", - "MessageNoRepositories": "No repositories.", - "HeaderNewRepository": "New Repository", - "LabelRepositoryUrl": "Repository URL", - "LabelRepositoryUrlHelp": "The location of the repository manifest you want to include.", - "LabelRepositoryName": "Repository Name", - "LabelRepositoryNameHelp": "A custom name to distinguish this repository from any others added to your server.", - "MessageAddRepository": "If you wish to add a repository, click the button next to the header and fill out the requested information.", - "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, and Albums. Click the + button to start creating collections.", - "MessageNoGenresAvailable": "Enable some metadata providers to pull genres from the internet.", - "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.", - "MessageNoServersAvailable": "No servers have been found using the automatic server discovery.", - "MessageNoTrailersFound": "Install the trailers 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 codes that were used to perform the reset.", - "MessagePlayAccessRestricted": "Playback of this content is currently restricted. Please contact your server administrator for more information.", - "MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.", - "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.", - "MessageReenableUser": "See below to reenable", - "MessageSettingsSaved": "Settings saved.", - "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:", - "MessageUnableToConnectToServer": "We're unable to connect to the selected server right now. Please ensure it is running and try again.", - "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders.", - "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", - "MessageSyncPlayEnabled": "SyncPlay enabled.", - "MessageSyncPlayDisabled": "SyncPlay disabled.", - "MessageSyncPlayUserJoined": "{0} has joined the group.", - "MessageSyncPlayUserLeft": "{0} has left the group.", - "MessageSyncPlayGroupWait": "{0} is buffering...", - "MessageSyncPlayNoGroupsAvailable": "No groups available. Start playing something first.", - "MessageSyncPlayPlaybackPermissionRequired": "Playback permission required.", - "MessageSyncPlayGroupDoesNotExist": "Failed to join group because it does not exist.", - "MessageSyncPlayCreateGroupDenied": "Permission required to create a group.", - "MessageSyncPlayJoinGroupDenied": "Permission required to use SyncPlay.", - "MessageSyncPlayLibraryAccessDenied": "Access to this content is restricted.", - "MessageSyncPlayErrorAccessingGroups": "An error occurred while accessing groups list.", - "MessageSyncPlayErrorNoActivePlayer": "No active player found. SyncPlay has been disabled.", - "MessageSyncPlayErrorMissingSession": "Failed to enable SyncPlay! Missing session.", - "MessageSyncPlayErrorMedia": "Failed to enable SyncPlay! Media error.", - "Metadata": "Metadata", - "MetadataManager": "Metadata Manager", - "MetadataSettingChangeHelp": "Changing metadata settings will affect new content that is added going forward. To refresh existing content, open the detail screen and click the refresh button, or perform bulk refreshes using the metadata manager.", - "MinutesAfter": "minutes after", - "MinutesBefore": "minutes before", - "Mobile": "Mobile", - "Monday": "Monday", - "MoreFromValue": "More from {0}", - "MoreUsersCanBeAddedLater": "More users can be added later from within the dashboard.", - "MoreMediaInfo": "Media Info", - "MoveLeft": "Move left", - "MoveRight": "Move right", - "MovieLibraryHelp": "Review the {0}movie naming guide{1}.", - "Movie": "Movie", - "Movies": "Movies", - "MusicAlbum": "Music Album", - "MusicArtist": "Music Artist", - "MusicLibraryHelp": "Review the {0}music naming guide{1}.", - "MusicVideo": "Music Video", - "Mute": "Mute", - "MySubtitles": "My Subtitles", - "Name": "Name", - "Never": "Never", - "NewCollection": "New Collection", - "NewCollectionHelp": "Collections allow you to create personalized groupings of movies and other library content.", - "NewCollectionNameExample": "Example: Star Wars Collection", - "NewEpisodes": "New episodes", - "NewEpisodesOnly": "New episodes only", - "News": "News", - "Next": "Next", - "NextUp": "Next Up", - "No": "No", - "NoCreatedLibraries": "Seems like you haven't created any libraries yet. {0}Would you like to create one now?{1}", - "NoNewDevicesFound": "No new devices found. To add a new tuner, close this dialog and enter the device information manually.", - "NoNextUpItemsMessage": "None found. Start watching your shows!", - "NoPluginConfigurationMessage": "This plugin has no settings to configure.", - "NoSubtitleSearchResultsFound": "No results found.", - "NoSubtitles": "None", - "NoSubtitlesHelp": "Subtitles will not be loaded by default. They can still be turned on manually during playback.", - "None": "None", - "Normal": "Normal", - "NumLocationsValue": "{0} folders", - "Off": "Off", - "OneChannel": "One channel", - "OnlyForcedSubtitles": "Only Forced", - "OnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.", - "OnlyImageFormats": "Only Image Formats (VOBSUB, PGS, SUB)", - "Option3D": "3D", - "OptionAdminUsers": "Administrators", - "OptionAlbum": "Album", - "OptionAlbumArtist": "Album Artist", - "OptionAllUsers": "All users", - "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding", - "OptionForceRemoteSourceTranscoding": "Force transcoding of remote media sources (like LiveTV)", - "OptionAllowBrowsingLiveTv": "Allow Live TV access", - "OptionAllowContentDownloading": "Allow media downloading and syncing", - "OptionAllowLinkSharing": "Allow social media sharing", - "OptionAllowLinkSharingHelp": "Only web pages containing media information are shared. Media files are never shared publicly. Shares are time-limited and will expire after {0} days.", - "OptionAllowManageLiveTv": "Allow Live TV recording management", - "OptionAllowMediaPlayback": "Allow media playback", - "OptionAllowMediaPlaybackTranscodingHelp": "Restricting access to transcoding may cause playback failures in Jellyfin apps due to unsupported media formats.", - "OptionAllowRemoteControlOthers": "Allow remote control of other users", - "OptionAllowRemoteSharedDevices": "Allow remote control of shared devices", - "OptionAllowRemoteSharedDevicesHelp": "DLNA devices are considered shared until a user begins controlling them.", - "OptionAllowSyncTranscoding": "Allow media downloading and syncing that requires transcoding", - "OptionAllowUserToManageServer": "Allow this user to manage the server", - "OptionAllowVideoPlaybackRemuxing": "Allow video playback that requires conversion without re-encoding", - "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding", - "OptionArtist": "Artist", - "OptionAscending": "Ascending", - "OptionAuto": "Auto", - "OptionAutomatic": "Auto", - "OptionAutomaticallyGroupSeries": "Automatically merge series that are spread across multiple folders", - "OptionAutomaticallyGroupSeriesHelp": "If enabled, series that are spread across multiple folders within this library will be automatically merged into a single series.", - "OptionBanner": "Banner", - "OptionBlockBooks": "Books", - "OptionBlockChannelContent": "Internet Channel Content", - "OptionBlockLiveTvChannels": "Live TV Channels", - "OptionBlockMovies": "Movies", - "OptionBlockMusic": "Music", - "OptionBlockTrailers": "Trailers", - "OptionBlockTvShows": "TV Shows", - "OptionBluray": "Blu-ray", - "OptionCaptionInfoExSamsung": "CaptionInfoEx (Samsung)", - "OptionCommunityRating": "Community Rating", - "OptionContinuing": "Continuing", - "OptionCriticRating": "Critic Rating", - "OptionCustomUsers": "Custom", - "OptionDaily": "Daily", - "OptionDateAdded": "Date Added", - "OptionDateAddedFileTime": "Use file creation date", - "OptionDateAddedImportTime": "Use date scanned into the library", - "OptionDatePlayed": "Date Played", - "OptionDescending": "Descending", - "OptionDisableUser": "Disable this user", - "OptionDisableUserHelp": "If disabled the server will not allow any connections from this user. Existing connections will be abruptly terminated.", - "OptionDislikes": "Dislikes", - "OptionDisplayFolderView": "Display a folder view to show plain media folders", - "OptionDisplayFolderViewHelp": "Display folders alongside your other media libraries. This can be useful if you'd like to have a plain folder view.", - "OptionDownloadArtImage": "Art", - "OptionDownloadBackImage": "Back", - "OptionDownloadBannerImage": "Banner", - "OptionDownloadBoxImage": "Box", - "OptionDownloadDiscImage": "Disc", - "OptionDownloadImagesInAdvance": "Download images in advance", - "OptionDownloadImagesInAdvanceHelp": "By default, most images are only downloaded when requested by a Jellyfin app. Enable this option to download all images in advance, as new media is imported. This may cause significantly longer library scans.", - "OptionDownloadLogoImage": "Logo", - "OptionDownloadMenuImage": "Menu", - "OptionDownloadPrimaryImage": "Primary", - "OptionDownloadThumbImage": "Thumb", - "OptionDvd": "DVD", - "OptionEmbedSubtitles": "Embed within container", - "OptionEnableAccessFromAllDevices": "Enable access from all devices", - "OptionEnableAccessToAllChannels": "Enable access to all channels", - "OptionEnableAccessToAllLibraries": "Enable access to all libraries", - "OptionEnableExternalContentInSuggestions": "Enable external content in suggestions", - "OptionEnableExternalContentInSuggestionsHelp": "Allow internet trailers and live TV programs to be included within suggested content.", - "OptionEnableForAllTuners": "Enable for all tuner devices", - "OptionEnableM2tsMode": "Enable M2ts mode", - "OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.", - "OptionEnded": "Ended", - "OptionEquals": "Equals", - "OptionEstimateContentLength": "Estimate content length when transcoding", - "OptionEveryday": "Every day", - "OptionExternallyDownloaded": "External download", - "OptionExtractChapterImage": "Enable chapter image extraction", - "OptionFavorite": "Favorites", - "OptionFriday": "Friday", - "OptionHasSpecialFeatures": "Special Features", - "OptionHasSubtitles": "Subtitles", - "OptionHasThemeSong": "Theme Song", - "OptionHasThemeVideo": "Theme Video", - "OptionHasTrailer": "Trailer", - "OptionHideUser": "Hide this user from login screens", - "OptionHideUserFromLoginHelp": "Useful for private or hidden administrator accounts. The user will need to sign in manually by entering their username and password.", - "OptionHlsSegmentedSubtitles": "HLS segmented subtitles", - "OptionHomeVideos": "Photos", - "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests", - "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.", - "OptionImdbRating": "IMDb Rating", - "OptionIsHD": "HD", - "OptionIsSD": "SD", - "OptionLikes": "Likes", - "OptionList": "List", - "OptionLoginAttemptsBeforeLockout": "Determines how many incorrect login attempts can be made before lockout occurs.", - "OptionLoginAttemptsBeforeLockoutHelp": "A value of zero means inheriting the default of three attempts for normal users and five for administrators. Setting this to -1 will disable the feature.", - "OptionMax": "Max", - "OptionMissingEpisode": "Missing Episodes", - "OptionMonday": "Monday", - "OptionNameSort": "Name", - "OptionNew": "New…", - "OptionNone": "None", - "OptionOnAppStartup": "On application startup", - "OptionOnInterval": "On an interval", - "OptionParentalRating": "Parental Rating", - "OptionPlainStorageFolders": "Display all folders as plain storage folders", - "OptionPlainStorageFoldersHelp": "If enabled, all folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".", - "OptionPlainVideoItems": "Display all videos as plain video items", - "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".", - "OptionPlayCount": "Play Count", - "OptionPlayed": "Played", - "OptionPoster": "Poster", - "OptionPosterCard": "Poster card", - "OptionPremiereDate": "Premiere Date", - "OptionProfileAudio": "Audio", - "OptionProfilePhoto": "Photo", - "OptionProfileVideo": "Video", - "OptionProfileVideoAudio": "Video Audio", - "OptionProtocolHls": "HTTP Live Streaming", - "OptionProtocolHttp": "HTTP", - "OptionRandom": "Random", - "OptionRegex": "Regex", - "OptionReleaseDate": "Release Date", - "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding", - "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.", - "OptionRequirePerfectSubtitleMatch": "Only download subtitles that are a perfect match for my video files", - "OptionRequirePerfectSubtitleMatchHelp": "Requiring a perfect match will filter subtitles to include only those that have been tested and verified with your exact video file. Unchecking this will increase the likelihood of subtitles being downloaded, but will increase the chances of mistimed or incorrect subtitle text.", - "OptionResElement": "res element", - "OptionResumable": "Resumable", - "OptionRuntime": "Runtime", - "OptionSaturday": "Saturday", - "OptionSaveMetadataAsHidden": "Save metadata and images as hidden files", - "OptionSaveMetadataAsHiddenHelp": "Changing this will apply to new metadata saved going forward. Existing metadata files will be updated the next time they are saved by Jellyfin Server.", - "OptionSpecialEpisode": "Specials", - "OptionSubstring": "Substring", - "OptionSunday": "Sunday", - "OptionThursday": "Thursday", - "OptionThumb": "Thumb", - "OptionThumbCard": "Thumb card", - "OptionTrackName": "Track Name", - "OptionTuesday": "Tuesday", - "OptionTvdbRating": "TVDB Rating", - "OptionUnairedEpisode": "Unaired Episodes", - "OptionUnplayed": "Unplayed", - "OptionWakeFromSleep": "Wake from sleep", - "OptionWednesday": "Wednesday", - "OptionWeekdays": "Weekdays", - "OptionWeekends": "Weekends", - "OptionWeekly": "Weekly", - "OriginalAirDateValue": "Original air date: {0}", - "OtherArtist": "Other Artist", - "Overview": "Overview", - "PackageInstallCancelled": "{0} (version {1}) installation cancelled.", - "PackageInstallCompleted": "{0} (version {1}) installation completed.", - "PackageInstallFailed": "{0} (version {1}) installation failed.", - "ParentalRating": "Parental rating", - "PasswordMatchError": "Password and password confirmation must match.", - "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 when this user requests a password reset", - "PasswordSaved": "Password saved.", - "People": "People", - "PerfectMatch": "Perfect match", - "Person": "Person", - "Photos": "Photos", - "PictureInPicture": "Picture in picture", - "PinCodeResetComplete": "The pin code has been reset.", - "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", - "PlaceFavoriteChannelsAtBeginning": "Place favorite channels at the beginning", - "Play": "Play", - "PlayAllFromHere": "Play all from here", - "PlaybackData": "Playback Data", - "PlayCount": "Play count", - "PlayFromBeginning": "Play from beginning", - "PlayNext": "Play next", - "PlayNextEpisodeAutomatically": "Play next episode automatically", - "PlaybackErrorNoCompatibleStream": "This client isn't compatible with the media and the server isn't sending a compatible media format.", - "Played": "Played", - "Playlists": "Playlists", - "PleaseAddAtLeastOneFolder": "Please add at least one folder to this library by clicking the Add button.", - "PleaseConfirmPluginInstallation": "Please click OK to confirm you've read the above and wish to proceed with the plugin installation.", - "PleaseEnterNameOrId": "Please enter a name or an external ID.", - "PleaseRestartServerName": "Please restart Jellyfin Server - {0}.", - "PleaseSelectTwoItems": "Please select at least two items.", - "PluginInstalledMessage": "The plugin has been successfully installed. Jellyfin Server will need to be restarted for changes to take effect.", - "PreferEmbeddedTitlesOverFileNames": "Prefer embedded titles over filenames", - "PreferEmbeddedTitlesOverFileNamesHelp": "This determines the default display title when no internet metadata or local metadata is available.", - "PreferEmbeddedEpisodeInfosOverFileNamesHelp": "This uses the episode information from the embedded metadata if available.", - "PreferEmbeddedEpisodeInfosOverFileNames": "Prefer embedded episode information over filenames", - "Premiere": "Premiere", - "Premieres": "Premieres", - "Previous": "Previous", - "Primary": "Primary", - "Producer": "Producer", - "ProductionLocations": "Production locations", - "Programs": "Programs", - "Quality": "Quality", - "QueueAllFromHere": "Queue all from here", - "Raised": "Raised", - "Rate": "Rate", - "RecentlyWatched": "Recently watched", - "RecommendationBecauseYouLike": "Because you like {0}", - "RecommendationBecauseYouWatched": "Because you watched {0}", - "RecommendationDirectedBy": "Directed by {0}", - "RecommendationStarring": "Starring {0}", - "Record": "Record", - "RecordSeries": "Record series", - "RecordingCancelled": "Recording cancelled.", - "RecordingPathChangeMessage": "Changing your recording folder will not migrate existing recordings from the old location to the new. You'll need to move them manually if desired.", - "RecordingScheduled": "Recording scheduled.", - "Recordings": "Recordings", - "Refresh": "Refresh", - "RefreshDialogHelp": "Metadata is refreshed based on settings and internet services that are enabled in the Jellyfin Server dashboard.", - "RefreshMetadata": "Refresh metadata", - "RefreshQueued": "Refresh queued.", - "ReleaseDate": "Release date", - "ReleaseGroup": "Release Group", - "RememberMe": "Remember Me", - "RemoveFromCollection": "Remove from collection", - "RemoveFromPlaylist": "Remove from playlist", - "Repeat": "Repeat", - "RepeatAll": "Repeat all", - "RepeatEpisodes": "Repeat episodes", - "RepeatMode": "Repeat Mode", - "RepeatOne": "Repeat one", - "ReplaceAllMetadata": "Replace all metadata", - "ReplaceExistingImages": "Replace existing images", - "ResumeAt": "Resume from {0}", - "Rewind": "Rewind", - "RunAtStartup": "Run at startup", - "Runtime": "Runtime", - "Saturday": "Saturday", - "Save": "Save", - "SaveChanges": "Save changes", - "SaveSubtitlesIntoMediaFolders": "Save subtitles into media folders", - "SaveSubtitlesIntoMediaFoldersHelp": "Storing subtitles next to video files will allow them to be more easily managed.", - "ScanForNewAndUpdatedFiles": "Scan for new and updated files", - "ScanLibrary": "Scan library", - "Schedule": "Schedule", - "Screenshot": "Screenshot", - "Screenshots": "Screenshots", - "Search": "Search", - "SearchForCollectionInternetMetadata": "Search the internet for artwork and metadata", - "SearchForMissingMetadata": "Search for missing metadata", - "SearchForSubtitles": "Search for Subtitles", - "SearchResults": "Search Results", - "Season": "Season", - "SelectAdminUsername": "Please select a username for the admin account.", - "SendMessage": "Send message", - "Series": "Series", - "SeriesCancelled": "Series cancelled.", - "SeriesDisplayOrderHelp": "Order episodes by air date, DVD order, or absolute numbering.", - "SeriesRecordingScheduled": "Series recording scheduled.", - "SeriesSettings": "Series settings", - "SeriesYearToPresent": "{0} - Present", - "ServerNameIsRestarting": "Jellyfin Server - {0} is restarting.", - "ServerNameIsShuttingDown": "Jellyfin Server - {0} is shutting down.", - "ServerRestartNeededAfterPluginInstall": "Jellyfin Server will need to be restarted after installing a plugin.", - "ServerUpdateNeeded": "This Jellyfin Server needs to be updated. To download the latest version, please visit {0}", - "Settings": "Settings", - "SettingsSaved": "Settings saved.", - "SettingsWarning": "Changing these values may cause instability or connectivity failures. If you experience any problems, we recommend changing them back to default.", - "Share": "Share", - "ShowAdvancedSettings": "Show advanced settings", - "ShowIndicatorsFor": "Show indicators for:", - "ShowLess": "Show less", - "ShowMore": "Show more", - "ShowTitle": "Show title", - "ShowYear": "Show year", - "Shows": "Shows", - "Shuffle": "Shuffle", - "New": "New", - "Filter": "Filter", - "SimultaneousConnectionLimitHelp": "The maximum number of allowed simultaneous streams. Enter 0 for no limit.", - "SkipEpisodesAlreadyInMyLibrary": "Don't record episodes that are already in my library", - "SkipEpisodesAlreadyInMyLibraryHelp": "Episodes will be compared using season and episode numbers, when available.", - "Small": "Small", - "SmallCaps": "Small Caps", - "Smaller": "Smaller", - "Smart": "Smart", - "SmartSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.", - "Songs": "Songs", - "Sort": "Sort", - "SortByValue": "Sort by {0}", - "SortChannelsBy": "Sort channels by:", - "SortName": "Sort name", - "Sports": "Sports", - "StopRecording": "Stop recording", - "Studios": "Studios", - "SubtitleAppearanceSettingsAlsoPassedToCastDevices": "These settings also apply to any Chromecast playback started by this device.", - "SubtitleAppearanceSettingsDisclaimer": "These settings will not apply to graphical subtitles (PGS, DVD, etc) or ASS/SSA subtitles that embed their own styles.", - "SubtitleDownloadersHelp": "Enable and rank your preferred subtitle downloaders in order of priority.", - "SubtitleOffset": "Subtitle Offset", - "Subtitles": "Subtitles", - "Suggestions": "Suggestions", - "Sunday": "Sunday", - "Sync": "Sync", - "SyncPlayAccessHelp": "Select the level of access this user has to the SyncPlay feature. SyncPlay enables to sync playback with other devices.", - "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.", - "TV": "TV", - "TabAccess": "Access", - "TabAdvanced": "Advanced", - "TabAlbumArtists": "Album Artists", - "TabAlbums": "Albums", - "TabArtists": "Artists", - "TabCatalog": "Catalog", - "TabRepositories": "Repositories", - "TabChannels": "Channels", - "TabCodecs": "Codecs", - "TabCollections": "Collections", - "TabContainers": "Containers", - "TabDashboard": "Dashboard", - "TabDevices": "Devices", - "TabDirectPlay": "Direct Play", - "TabDisplay": "Display", - "TabDVR": "DVR", - "TabEpisodes": "Episodes", - "TabFavorites": "Favorites", - "TabGenres": "Genres", - "TabGuide": "Guide", - "TabInfo": "Info", - "TabLatest": "Latest", - "TabLiveTV": "Live TV", - "TabLogs": "Logs", - "TabMetadata": "Metadata", - "TabMovies": "Movies", - "TabMusic": "Music", - "TabMusicVideos": "Music Videos", - "TabMyPlugins": "My Plugins", - "TabNetworks": "Networks", - "TabNetworking": "Networking", - "TabNfoSettings": "NFO Settings", - "TabNotifications": "Notifications", - "TabOther": "Other", - "TabParentalControl": "Parental Control", - "TabPassword": "Password", - "TabPlayback": "Playback", - "TabPlaylist": "Playlist", - "TabPlaylists": "Playlists", - "TabPlugins": "Plugins", - "TabProfile": "Profile", - "TabProfiles": "Profiles", - "TabRecordings": "Recordings", - "TabResponses": "Responses", - "TabResumeSettings": "Resume", - "TabScheduledTasks": "Scheduled Tasks", - "TabSeries": "Series", - "TabServer": "Server", - "TabSettings": "Settings", - "TabShows": "Shows", - "TabSongs": "Songs", - "TabStreaming": "Streaming", - "TabSuggestions": "Suggestions", - "TabTrailers": "Trailers", - "TabTranscoding": "Transcoding", - "TabUpcoming": "Upcoming", - "TabUsers": "Users", - "Tags": "Tags", - "TagsValue": "Tags: {0}", - "TellUsAboutYourself": "Tell us about yourself", - "ThemeSongs": "Theme songs", - "ThemeVideos": "Theme videos", - "TheseSettingsAffectSubtitlesOnThisDevice": "These settings affect subtitles on this device", - "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process. To begin, please select your preferred language.", - "Thumb": "Thumb", - "Thursday": "Thursday", - "TitleHardwareAcceleration": "Hardware Acceleration", - "TitleHostingSettings": "Hosting Settings", - "TitlePlayback": "Playback", - "Track": "Track", - "TrackCount": "{0} tracks", - "Trailers": "Trailers", - "Transcoding": "Transcoding", - "Tuesday": "Tuesday", - "TvLibraryHelp": "Review the {0}TV naming guide{1}.", - "Uniform": "Uniform", - "UninstallPluginConfirmation": "Are you sure you wish to uninstall {0}?", - "UninstallPluginHeader": "Uninstall Plugin", - "Unmute": "Unmute", - "Unplayed": "Unplayed", - "Unrated": "Unrated", - "Up": "Up", - "Upload": "Upload", - "UserAgentHelp": "Supply a custom user-agent HTTP header.", - "UserProfilesIntro": "Jellyfin includes support for user profiles with granular display settings, play state, and parental controls.", - "ValueAlbumCount": "{0} albums", - "ValueAudioCodec": "Audio Codec: {0}", - "ValueCodec": "Codec: {0}", - "ValueConditions": "Conditions: {0}", - "ValueContainer": "Container: {0}", - "ValueDiscNumber": "Disc {0}", - "ValueEpisodeCount": "{0} episodes", - "ValueMinutes": "{0} min", - "ValueMovieCount": "{0} movies", - "ValueMusicVideoCount": "{0} music videos", - "ValueOneAlbum": "1 album", - "ValueOneEpisode": "1 episode", - "ValueOneMovie": "1 movie", - "ValueOneMusicVideo": "1 music video", - "ValueOneSeries": "1 series", - "ValueOneSong": "1 song", - "ValueSeconds": "{0} seconds", - "ValueSeriesCount": "{0} series", - "ValueSongCount": "{0} songs", - "ValueSpecialEpisodeName": "Special - {0}", - "ValueTimeLimitMultiHour": "Time limit: {0} hours", - "ValueTimeLimitSingleHour": "Time limit: 1 hour", - "ValueVideoCodec": "Video Codec: {0}", - "Vertical": "Vertical", - "VideoRange": "Video range", - "ViewAlbum": "View album", - "ViewAlbumArtist": "View album artist", - "ViewPlaybackInfo": "View playback info", - "Watched": "Watched", - "Wednesday": "Wednesday", - "WelcomeToProject": "Welcome to Jellyfin!", - "Whitelist": "Whitelist", - "WizardCompleted": "That's all we need for now. Jellyfin has begun collecting information about your media library. Check out some of our apps, and then click Finish to view the Dashboard.", - "Writer": "Writer", - "Writers": "Writers", - "XmlDocumentAttributeListHelp": "These attributes are applied to the root element of every XML response.", - "XmlTvKidsCategoriesHelp": "Programs with these categories will be displayed as programs for children. Separate multiple with '|'.", - "XmlTvMovieCategoriesHelp": "Programs with these categories will be displayed as movies. Separate multiple with '|'.", - "XmlTvNewsCategoriesHelp": "Programs with these categories will be displayed as news programs. Separate multiple with '|'.", - "XmlTvPathHelp": "A path to a XMLTV file. Jellyfin will read this file and periodically check it for updates. You are responsible for creating and updating the file.", - "XmlTvSportsCategoriesHelp": "Programs with these categories will be displayed as sports programs. Separate multiple with '|'.", - "Yadif": "YADIF", - "YadifBob": "YADIF Bob", - "Yes": "Yes", - "Yesterday": "Yesterday", - "PathNotFound": "The path could not be found. Please ensure the path is valid and try again.", - "WriteAccessRequired": "Jellyfin Server requires write access to this folder. Please ensure write access and try again.", - "ListPaging": "{0}-{1} of {2}", - "PersonRole": "as {0}", - "LastSeen": "Last seen {0}", - "DailyAt": "Daily at {0}", - "WeeklyAt": "{0}s at {1}", - "OnWakeFromSleep": "On wake from sleep", - "EveryXMinutes": "Every {0} minutes", - "EveryHour": "Every hour", - "EveryXHours": "Every {0} hours", - "OnApplicationStartup": "On application startup", - "UnsupportedPlayback": "Jellyfin cannot decrypt content protected by DRM but all content will be attempted regardless, including protected titles. Some files may appear completely black due to encryption or other unsupported features, such as interactive titles.", - "EnableBlurhash": "Enable blurred placeholders for images", - "EnableBlurhashHelp": "Images that are still being loaded will be displayed with a blurred placeholder", - "ButtonSyncPlay": "SyncPlay", - "ButtonCast": "Cast", - "ButtonPlayer": "Player", - "StopPlayback": "Stop playback", - "ClearQueue": "Clear queue" + "Absolute": "Absolute", + "AccessRestrictedTryAgainLater": "Access is currently restricted. Please try again later.", + "Actor": "Actor", + "Add": "Add", + "AddToCollection": "Add to collection", + "AddToPlayQueue": "Add to play queue", + "AddToPlaylist": "Add to playlist", + "AddedOnValue": "Added {0}", + "AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.", + "AirDate": "Air date", + "Aired": "Aired", + "Album": "Album", + "AlbumArtist": "Album Artist", + "Albums": "Albums", + "Alerts": "Alerts", + "All": "All", + "AllChannels": "All channels", + "AllComplexFormats": "All Complex Formats (ASS, SSA, VOBSUB, PGS, SUB, IDX, …)", + "AllEpisodes": "All episodes", + "AllLanguages": "All languages", + "AllLibraries": "All libraries", + "AllowHWTranscodingHelp": "Allow the tuner to transcode streams on the fly. This may help reduce transcoding required by the server.", + "AllowMediaConversion": "Allow media conversion", + "AllowMediaConversionHelp": "Grant or deny access to the convert media feature.", + "AllowOnTheFlySubtitleExtraction": "Allow subtitle extraction on the fly", + "AllowOnTheFlySubtitleExtractionHelp": "Embedded subtitles can be extracted from videos and delivered to clients in plain text, in order to help prevent video transcoding. On some systems this can take a long time and cause video playback to stall during the extraction process. Disable this to have embedded subtitles burned in with video transcoding when they are not natively supported by the client device.", + "AllowFfmpegThrottling": "Throttle Transcodes", + "AllowFfmpegThrottlingHelp": "When a transcode or remux gets far enough ahead from the current playback position, pause the process so it will consume less resources. This is most useful when watching without seeking often. Turn this off if you experience playback issues.", + "AllowRemoteAccess": "Allow remote connections to this server.", + "AllowRemoteAccessHelp": "If unchecked, all remote connections will be blocked.", + "AllowedRemoteAddressesHelp": "Comma separated list of IP addresses or IP/netmask entries for networks that will be allowed to connect remotely. If left blank, all remote addresses will be allowed.", + "AlwaysPlaySubtitles": "Always Play", + "AlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.", + "AnyLanguage": "Any Language", + "Anytime": "Anytime", + "AroundTime": "Around", + "Art": "Art", + "Artist": "Artist", + "Artists": "Artists", + "AsManyAsPossible": "As many as possible", + "Ascending": "Ascending", + "AskAdminToCreateLibrary": "Ask an administrator to create a library.", + "AspectRatio": "Aspect Ratio", + "Audio": "Audio", + "AuthProviderHelp": "Select an authentication provider to be used to authenticate this user's password.", + "Auto": "Auto", + "Authorize": "Authorize", + "Backdrop": "Backdrop", + "Backdrops": "Backdrops", + "Banner": "Banner", + "BirthDateValue": "Born: {0}", + "BirthLocation": "Birth location", + "BirthPlaceValue": "Birth place: {0}", + "Blacklist": "Blacklist", + "BookLibraryHelp": "Audio and text books are supported. Review the {0} book naming guide {1}.", + "Books": "Books", + "Box": "Box", + "BoxSet": "Box Set", + "BoxRear": "Box (rear)", + "Browse": "Browse", + "MessageBrowsePluginCatalog": "Browse our plugin catalog to view available plugins.", + "BurnSubtitlesHelp": "Determines if the server should burn in subtitles when transcoding videos. Avoiding this will greatly improve performance. Select Auto to burn image based formats (VOBSUB, PGS, SUB, IDX, …) and certain ASS or SSA subtitles.", + "ButtonActivate": "Activate", + "ButtonAddImage": "Add Image", + "ButtonAddMediaLibrary": "Add Media Library", + "ButtonAddScheduledTaskTrigger": "Add Trigger", + "ButtonAddServer": "Add Server", + "ButtonAddUser": "Add User", + "ButtonArrowLeft": "Left", + "ButtonArrowRight": "Right", + "ButtonAudioTracks": "Audio Tracks", + "ButtonBack": "Back", + "ButtonCancel": "Cancel", + "ButtonChangeServer": "Change Server", + "ButtonEditOtherUserPreferences": "Edit this user's profile, image and personal preferences.", + "ButtonForgotPassword": "Forgot Password", + "ButtonFullscreen": "Fullscreen", + "ButtonGotIt": "Got It", + "ButtonInfo": "Info", + "ButtonLibraryAccess": "Library access", + "ButtonManualLogin": "Manual Login", + "ButtonMore": "More", + "ButtonNetwork": "Network", + "ButtonNextTrack": "Next track", + "ButtonOk": "Ok", + "ButtonOpen": "Open", + "ButtonParentalControl": "Parental control", + "ButtonPause": "Pause", + "ButtonPreviousTrack": "Previous track", + "ButtonQuickStartGuide": "Quick Start Guide", + "ButtonRefreshGuideData": "Refresh Guide Data", + "ButtonRemove": "Remove", + "ButtonRename": "Rename", + "ButtonResetEasyPassword": "Reset easy pin code", + "ButtonResume": "Resume", + "ButtonRevoke": "Revoke", + "ButtonScanAllLibraries": "Scan All Libraries", + "ButtonSelectDirectory": "Select Directory", + "ButtonSelectView": "Select view", + "ButtonSend": "Send", + "ButtonShutdown": "Shutdown", + "ButtonSignIn": "Sign In", + "ButtonSignOut": "Sign Out", + "ButtonStart": "Start", + "ButtonStop": "Stop", + "ButtonSplit": "Split", + "ButtonSubmit": "Submit", + "ButtonTogglePlaylist": "Playlist", + "ButtonTrailer": "Trailer", + "ButtonUninstall": "Uninstall", + "ButtonUseQuickConnect": "Use Quick Connect", + "ButtonWebsite": "Website", + "CancelRecording": "Cancel recording", + "CancelSeries": "Cancel series", + "Categories": "Categories", + "ChangingMetadataImageSettingsNewContent": "Changes to metadata or artwork downloading settings will only apply to new content added to your library. To apply the changes to existing titles, you'll need to refresh their metadata manually.", + "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.", + "ChannelNameOnly": "Channel {0} only", + "ChannelNumber": "Channel number", + "Channels": "Channels", + "CinemaModeConfigurationHelp": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.", + "ClientSettings": "Client Settings", + "Collections": "Collections", + "ColorPrimaries": "Color primaries", + "ColorSpace": "Color space", + "ColorTransfer": "Color transfer", + "CommunityRating": "Community rating", + "Composer": "Composer", + "ConfigureDateAdded": "Configure how date added is determined in the dashboard under the library settings", + "ConfirmDeleteImage": "Delete image?", + "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?", + "ConfirmDeleteItems": "Deleting these items will delete them from both the file system and your media library. Are you sure you wish to continue?", + "ConfirmDeletion": "Confirm Deletion", + "ConfirmEndPlayerSession": "Would you like to shutdown Jellyfin on {0}?", + "Connect": "Connect", + "ContinueWatching": "Continue watching", + "Continuing": "Continuing", + "CopyStreamURL": "Copy Stream URL", + "CopyStreamURLSuccess": "URL copied successfully.", + "CriticRating": "Critic rating", + "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.", + "Data": "Data", + "DateAdded": "Date added", + "DatePlayed": "Date played", + "DeathDateValue": "Died: {0}", + "Default": "Default", + "ErrorDefault": "There was an error processing the request. Please try again later.", + "DefaultMetadataLangaugeDescription": "These are your defaults and can be customized on a per-library basis.", + "DefaultSubtitlesHelp": "Subtitles are loaded based on the default and forced flags in the embedded metadata. Language preferences are considered when multiple options are available.", + "DeinterlaceMethodHelp": "Select the deinterlacing method to use when software transcoding interlaced content. When hardware acceleration supporting hardware deinterlacing is enabled the hardware deinterlacer will be used instead of this setting.", + "Delete": "Delete", + "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", + "DeleteImage": "Delete Image", + "DeleteImageConfirmation": "Are you sure you wish to delete this image?", + "DeleteMedia": "Delete media", + "DeleteUser": "Delete User", + "DeleteUserConfirmation": "Are you sure you wish to delete this user?", + "Depressed": "Depressed", + "Descending": "Descending", + "Desktop": "Desktop", + "DetectingDevices": "Detecting devices", + "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", + "DirectPlaying": "Direct playing", + "DirectStreamHelp1": "The media is compatible with the device regarding resolution and media type (H.264, AC3, etc), but in an incompatible file container (mkv, avi, wmv, etc). The video will be re-packaged on the fly before being sent to the device.", + "DirectStreamHelp2": "Direct stream uses very little processing power with a minimal loss in video quality.", + "DirectStreaming": "Direct streaming", + "Director": "Director", + "Directors": "Directors", + "Disc": "Disc", + "Disconnect": "Disconnect", + "Display": "Display", + "DisplayInMyMedia": "Display on home screen", + "DisplayInOtherHomeScreenSections": "Display in home screen sections such as latest media and continue watching", + "DisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", + "DisplayMissingEpisodesWithinSeasonsHelp": "This must also be enabled for TV libraries in the server configuration.", + "DisplayModeHelp": "Select the layout style you want for the interface.", + "DoNotRecord": "Do not record", + "Down": "Down", + "Download": "Download", + "DownloadsValue": "{0} downloads", + "DrmChannelsNotImported": "Channels with DRM will not be imported.", + "DropShadow": "Drop Shadow", + "EasyPasswordHelp": "Your easy pin code is used for offline access on supported clients and can also be used for easy in-network sign in.", + "Edit": "Edit", + "EditImages": "Edit images", + "EditMetadata": "Edit metadata", + "EditSubtitles": "Edit subtitles", + "EnableAutoCast": "Set as Default", + "EnableBackdropsHelp": "Display backdrops in the background of some pages while browsing the library.", + "EnableCinemaMode": "Cinema mode", + "EnableColorCodedBackgrounds": "Color coded backgrounds", + "EnableDecodingColorDepth10Hevc": "Enable 10-Bit hardware decoding for HEVC", + "EnableDecodingColorDepth10Vp9": "Enable 10-Bit hardware decoding for VP9", + "EnableDisplayMirroring": "Display mirroring", + "EnableExternalVideoPlayers": "External video players", + "EnableExternalVideoPlayersHelp": "An external player menu will be shown when starting video playback.", + "EnableHardwareEncoding": "Enable hardware encoding", + "EnableNextVideoInfoOverlay": "Show next video info during playback", + "EnableNextVideoInfoOverlayHelp": "At the end of a video, display info about the next video coming up in the current playlist.", + "EnablePhotos": "Display photos", + "EnablePhotosHelp": "Images will be detected and displayed alongside other media files.", + "EnableQuickConnect": "Enable quick connect on this server", + "EnableStreamLooping": "Auto-loop live streams", + "EnableStreamLoopingHelp": "Enable this if live streams only contain a few seconds of data and need to be continuously requested. Enabling this when not needed may cause problems.", + "EnableThemeSongsHelp": "Play theme songs in the background while browsing the library.", + "EnableThemeVideosHelp": "Play theme videos in the background while browsing the library.", + "EnableDetailsBanner": "Details Banner", + "EnableDetailsBannerHelp": "Display a banner image at the top of the item details page.", + "Ended": "Ended", + "EndsAtValue": "Ends at {0}", + "Episode": "Episode", + "Episodes": "Episodes", + "ErrorAddingListingsToSchedulesDirect": "There was an error adding the lineup to your Schedules Direct account. Schedules Direct only allows a limited number of lineups per account. You may need to log into the Schedules Direct website and remove others listings from your account before proceeding.", + "ErrorAddingMediaPathToVirtualFolder": "There was an error adding the media path. Please ensure the path is valid and Jellyfin has access to that location.", + "ErrorAddingTunerDevice": "There was an error adding the tuner device. Please ensure it is accessible and try again.", + "ErrorAddingXmlTvFile": "There was an error accessing the XMLTV file. Please ensure the file exists and try again.", + "ErrorDeletingItem": "There was an error deleting the item from the server. Please check that Jellyfin has write access to the media folder and try again.", + "ErrorGettingTvLineups": "There was an error downloading TV lineups. Please ensure your information is correct and try again.", + "ErrorStartHourGreaterThanEnd": "End time must be greater than the start time.", + "ErrorPleaseSelectLineup": "Please select a lineup and try again. If no lineups are available, then please check that your username, password, and postal code is correct.", + "ErrorSavingTvProvider": "There was an error saving the TV provider. Please ensure it is accessible and try again.", + "EveryNDays": "Every {0} days", + "ExitFullscreen": "Exit full screen", + "ExtraLarge": "Extra Large", + "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, resource intensive, and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "Extras": "Extras", + "FFmpegSavePathNotFound": "We're unable to locate FFmpeg using the path you've entered. FFprobe is also required and must exist in the same folder. These components are normally bundled together in the same download. Please check the path and try again.", + "FastForward": "Fast-forward", + "Favorite": "Favorite", + "Favorites": "Favorites", + "Features": "Features", + "FetchingData": "Fetching additional data", + "File": "File", + "FileNotFound": "File not found.", + "FileReadCancelled": "The file read has been canceled.", + "FileReadError": "An error occurred while reading the file.", + "Filters": "Filters", + "Folders": "Folders", + "FormatValue": "Format: {0}", + "Friday": "Friday", + "Fullscreen": "Full screen", + "General": "General", + "Genre": "Genre", + "Genres": "Genres", + "Other": "Other", + "GroupBySeries": "Group by series", + "GroupVersions": "Group versions", + "GuestStar": "Guest star", + "Guide": "Guide", + "GuideProviderLogin": "Login", + "GuideProviderSelectListings": "Select Listings", + "H264CrfHelp": "The Constant Rate Factor (CRF) is the default quality setting for the x264 encoder. You can set the values between 0 and 51, where lower values would result in better quality (at the expense of higher file sizes). Sane values are between 18 and 28. The default for x264 is 23, so you can use this as a starting point.", + "EncoderPresetHelp": "Choose a faster value to improve performance, or a slower value to improve quality.", + "HDPrograms": "HD programs", + "HardwareAccelerationWarning": "Enabling hardware acceleration may cause instability in some environments. Ensure that your operating system and video drivers are fully up to date. If you have difficulty playing video after enabling this, you'll need to change the setting back to None.", + "HeaderAccessSchedule": "Access Schedule", + "HeaderAccessScheduleHelp": "Create an access schedule to limit access to certain hours.", + "HeaderActiveDevices": "Active Devices", + "HeaderActiveRecordings": "Active Recordings", + "HeaderActivity": "Activity", + "HeaderAddToCollection": "Add to Collection", + "HeaderAddToPlaylist": "Add to Playlist", + "HeaderAddUpdateImage": "Add/Update Image", + "HeaderAdditionalParts": "Additional Parts", + "HeaderAdmin": "Admin", + "HeaderAlbumArtists": "Album Artists", + "HeaderAlert": "Alert", + "HeaderAllowMediaDeletionFrom": "Allow Media Deletion From", + "HeaderApiKey": "API Key", + "HeaderApiKeys": "API Keys", + "HeaderApiKeysHelp": "External applications are required to have an API key in order to communicate with the server. Keys are issued by logging in with a normal user account or manually granting the application a key.", + "ApiKeysCaption": "List of the currently enabled API keys", + "HeaderApp": "App", + "HeaderAppearsOn": "Appears On", + "HeaderAudioBooks": "Audio Books", + "HeaderAudioSettings": "Audio Settings", + "HeaderBlockItemsWithNoRating": "Block items with no or unrecognized rating information:", + "HeaderBranding": "Branding", + "HeaderCancelRecording": "Cancel Recording", + "HeaderCancelSeries": "Cancel Series", + "HeaderCastAndCrew": "Cast & Crew", + "HeaderChannelAccess": "Channel Access", + "HeaderChapterImages": "Chapter Images", + "HeaderCodecProfile": "Codec Profile", + "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.", + "HeaderConfigureRemoteAccess": "Configure Remote Access", + "HeaderConfirmPluginInstallation": "Confirm Plugin Installation", + "HeaderConfirmProfileDeletion": "Confirm Profile Deletion", + "HeaderConfirmRevokeApiKey": "Revoke API Key", + "HeaderConnectToServer": "Connect to Server", + "HeaderConnectionFailure": "Connection Failure", + "HeaderContainerProfile": "Container Profile", + "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.", + "HeaderContinueListening": "Continue Listening", + "HeaderContinueWatching": "Continue Watching", + "HeaderCustomDlnaProfiles": "Custom Profiles", + "HeaderDateIssued": "Date Issued", + "HeaderDefaultRecordingSettings": "Default Recording Settings", + "HeaderDeleteDevice": "Delete Device", + "HeaderDeleteItem": "Delete Item", + "HeaderDeleteItems": "Delete Items", + "HeaderDeleteProvider": "Delete Provider", + "HeaderDeleteTaskTrigger": "Delete Task Trigger", + "HeaderDetectMyDevices": "Detect My Devices", + "HeaderDeveloperInfo": "Developer Info", + "HeaderDeviceAccess": "Device Access", + "HeaderDevices": "Devices", + "HeaderDirectPlayProfile": "Direct Play Profile", + "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.", + "HeaderDownloadSync": "Download & Sync", + "HeaderDVR": "DVR", + "HeaderEasyPinCode": "Easy Pin Code", + "HeaderEditImages": "Edit Images", + "HeaderEnabledFields": "Enabled Fields", + "HeaderEnabledFieldsHelp": "Uncheck a field to lock it and prevent its data from being changed.", + "HeaderError": "Error", + "HeaderExternalIds": "External IDs:", + "HeaderFeatureAccess": "Feature Access", + "HeaderFetchImages": "Fetch Images:", + "HeaderFetcherSettings": "Fetcher Settings", + "HeaderForKids": "For Kids", + "HeaderFrequentlyPlayed": "Frequently Played", + "HeaderGuideProviders": "TV Guide Data Providers", + "HeaderHttpHeaders": "HTTP Headers", + "HeaderHttpsSettings": "HTTPS Settings", + "HeaderIdentification": "Identification", + "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.", + "HeaderIdentificationHeader": "Identification Header", + "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.", + "HeaderImageOptions": "Image Options", + "HeaderImageSettings": "Image Settings", + "HeaderInstall": "Install", + "HeaderInstantMix": "Instant Mix", + "HeaderKeepRecording": "Keep Recording", + "HeaderKeepSeries": "Keep Series", + "HeaderKodiMetadataHelp": "To enable or disable NFO metadata, edit a library and locate the metadata savers section.", + "HeaderLatestEpisodes": "Latest Episodes", + "HeaderLatestMedia": "Latest Media", + "HeaderLatestMovies": "Latest Movies", + "HeaderLatestMusic": "Latest Music", + "HeaderLatestRecordings": "Latest Recordings", + "HeaderLibraries": "Libraries", + "HeaderLibraryAccess": "Library Access", + "HeaderLibraryFolders": "Library Folders", + "HeaderLibraryOrder": "Library Order", + "HeaderLibrarySettings": "Library Settings", + "HeaderLiveTvTunerSetup": "Live TV Tuner Setup", + "HeaderLoginFailure": "Login Failure", + "HeaderMedia": "Media", + "HeaderMediaFolders": "Media Folders", + "HeaderMetadataSettings": "Metadata Settings", + "HeaderMoreLikeThis": "More Like This", + "HeaderMusicQuality": "Music Quality", + "HeaderMyDevice": "My Device", + "HeaderMyMedia": "My Media", + "HeaderMyMediaSmall": "My Media (small)", + "HeaderNavigation": "Navigation", + "HeaderNewApiKey": "New API Key", + "HeaderNewDevices": "New Devices", + "HeaderNextEpisodePlayingInValue": "Next Episode Playing in {0}", + "HeaderNextVideoPlayingInValue": "Next Video Playing in {0}", + "HeaderOnNow": "On Now", + "HeaderOtherItems": "Other Items", + "HeaderParentalRatings": "Parental Ratings", + "HeaderPassword": "Password", + "HeaderPasswordReset": "Password Reset", + "HeaderPaths": "Paths", + "HeaderPhotoAlbums": "Photo Albums", + "HeaderPinCodeReset": "Reset Pin Code", + "HeaderPlayAll": "Play All", + "HeaderPlayOn": "Play On", + "HeaderPlayback": "Media Playback", + "HeaderPlaybackError": "Playback Error", + "HeaderPleaseSignIn": "Please sign in", + "HeaderPluginInstallation": "Plugin Installation", + "HeaderPreferredMetadataLanguage": "Preferred Metadata Language", + "HeaderProfileInformation": "Profile Information", + "HeaderProfileServerSettingsHelp": "These values control how the server will present itself to clients.", + "HeaderRecentlyPlayed": "Recently Played", + "HeaderRecordingOptions": "Recording Options", + "HeaderRecordingPostProcessing": "Recording Post Processing", + "HeaderRemoteAccessSettings": "Remote Access Settings", + "HeaderRemoteControl": "Remote Control", + "HeaderRemoveMediaFolder": "Remove Media Folder", + "HeaderRemoveMediaLocation": "Remove Media Location", + "HeaderResponseProfile": "Response Profile", + "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.", + "HeaderRevisionHistory": "Revision History", + "HeaderRunningTasks": "Running Tasks", + "HeaderScenes": "Scenes", + "HeaderSeasons": "Seasons", + "HeaderSecondsValue": "{0} Seconds", + "HeaderSelectCertificatePath": "Select Certificate Path", + "HeaderSelectMetadataPath": "Select Metadata Path", + "HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to use for metadata. The folder must be writeable.", + "HeaderSelectPath": "Select Path", + "HeaderSelectServerCachePath": "Select Server Cache Path", + "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.", + "HeaderSelectTranscodingPath": "Select Transcoding Temporary Path", + "HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcode files. The folder must be writeable.", + "HeaderSendMessage": "Send Message", + "HeaderSeriesOptions": "Series Options", + "HeaderSeriesStatus": "Series Status", + "HeaderServerAddressSettings": "Server Address Settings", + "HeaderServerSettings": "Server Settings", + "HeaderSetupLibrary": "Setup your media libraries", + "HeaderSortBy": "Sort By", + "HeaderSortOrder": "Sort Order", + "HeaderSpecialEpisodeInfo": "Special Episode Info", + "HeaderStartNow": "Start Now", + "HeaderStatus": "Status", + "HeaderStopRecording": "Stop Recording", + "HeaderSubtitleAppearance": "Subtitle Appearance", + "HeaderSubtitleDownloads": "Subtitle Downloads", + "HeaderSubtitleProfile": "Subtitle Profile", + "HeaderSubtitleProfiles": "Subtitle Profiles", + "HeaderSubtitleProfilesHelp": "Subtitle profiles describe the subtitle formats supported by the device.", + "HeaderSyncPlaySelectGroup": "Join a group", + "HeaderSyncPlayEnabled": "SyncPlay enabled", + "HeaderSystemDlnaProfiles": "System Profiles", + "HeaderTaskTriggers": "Task Triggers", + "HeaderThisUserIsCurrentlyDisabled": "This user is currently disabled", + "HeaderTracks": "Tracks", + "HeaderTranscodingProfile": "Transcoding Profile", + "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.", + "HeaderTunerDevices": "Tuner Devices", + "HeaderTuners": "Tuners", + "HeaderTypeImageFetchers": "{0} Image Fetchers", + "HeaderTypeText": "Enter Text", + "HeaderUpcomingOnTV": "Upcoming On TV", + "HeaderUploadImage": "Upload Image", + "HeaderUser": "User", + "HeaderUsers": "Users", + "HeaderVideoQuality": "Video Quality", + "HeaderVideoType": "Video Type", + "HeaderVideoTypes": "Video Types", + "HeaderVideos": "Videos", + "HeaderXmlDocumentAttribute": "Xml Document Attribute", + "HeaderXmlDocumentAttributes": "Xml Document Attributes", + "HeaderXmlSettings": "Xml Settings", + "HeaderYears": "Years", + "Help": "Help", + "Hide": "Hide", + "HideWatchedContentFromLatestMedia": "Hide watched content from latest media", + "Home": "Home", + "Horizontal": "Horizontal", + "HttpsRequiresCert": "To enable secure connections, you will need to supply a trusted SSL certificate, such as Let's Encrypt. Please either supply a certificate, or disable secure connections.", + "Identify": "Identify", + "Image": "Image", + "Images": "Images", + "ImportFavoriteChannelsHelp": "Only channels that are marked as favorite on the tuner device will be imported.", + "ImportMissingEpisodesHelp": "Information about missing episodes will be imported into your database and displayed within seasons and series. This may cause significantly longer library scans.", + "InstallingPackage": "Installing {0} (version {1})", + "InstantMix": "Instant mix", + "ItemCount": "{0} items", + "Items": "Items", + "Kids": "Kids", + "KnownProxiesHelp": "Comma separated list of IP addresses of known proxies used when connecting to your Jellyfin instance. This is required to make proper use of X-Forwarded-For headers. Requires a reboot after saving.", + "Label3DFormat": "3D format:", + "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", + "LabelAccessDay": "Day of week:", + "LabelAccessEnd": "End time:", + "LabelAccessStart": "Start time:", + "LabelAirDays": "Air days:", + "LabelAirTime": "Air time:", + "LabelAirsAfterSeason": "Airs after season:", + "LabelAirsBeforeEpisode": "Airs before episode:", + "LabelAirsBeforeSeason": "Airs before season:", + "LabelAlbum": "Album:", + "LabelAlbumArtMaxResHelp": "Maximum resolution of album art exposed via the upnp:albumArtURI property.", + "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some devices require a specific value, regardless of the size of the image.", + "LabelAlbumArtMaxHeight": "Album art max height:", + "LabelAlbumArtMaxWidth": "Album art max width:", + "LabelAlbumArtPN": "Album art PN:", + "LabelAlbumArtists": "Album artists:", + "LabelAllowHWTranscoding": "Allow hardware transcoding", + "LabelAllowedRemoteAddresses": "Remote IP address filter:", + "LabelAllowedRemoteAddressesMode": "Remote IP address filter mode:", + "LabelAppName": "App name", + "LabelAppNameExample": "Example: Sickbeard, Sonarr", + "LabelArtists": "Artists:", + "LabelArtistsHelp": "Separate multiple artists with a semicolon.", + "LabelAudioBitDepth": "Audio bit depth:", + "LabelAudioBitrate": "Audio bitrate:", + "LabelAudioChannels": "Audio channels:", + "LabelAudioCodec": "Audio codec:", + "LabelAudioLanguagePreference": "Preferred audio language:", + "LabelAudioSampleRate": "Audio sample rate:", + "LabelAuthProvider": "Authentication Provider:", + "LabelAutomaticallyRefreshInternetMetadataEvery": "Automatically refresh metadata from the internet:", + "LabelBindToLocalNetworkAddress": "Bind to local network address:", + "LabelBindToLocalNetworkAddressHelp": "Override the local IP address for the HTTP server. If left empty, the server will bind to all available addresses. Changing this value requires a restart.", + "LabelBirthDate": "Birth date:", + "LabelBirthYear": "Birth year:", + "LabelBitrate": "Bitrate:", + "LabelBlastMessageInterval": "Alive message interval", + "LabelBlastMessageIntervalHelp": "Determines the duration in seconds between blast alive messages.", + "LabelBlockContentWithTags": "Block items with tags:", + "LabelBurnSubtitles": "Burn subtitles:", + "LabelCache": "Cache:", + "LabelCachePath": "Cache path:", + "LabelCachePathHelp": "Specify a custom location for server cache files such as images. Leave blank to use the server default.", + "LabelCancelled": "Cancelled", + "LabelCertificatePassword": "Certificate password:", + "LabelCertificatePasswordHelp": "If your certificate requires a password, please enter it here.", + "LabelChannels": "Channels:", + "LabelCollection": "Collection:", + "LabelCommunityRating": "Community rating:", + "LabelContentType": "Content type:", + "LabelCorruptedFrames": "Corrupted frames:", + "LabelCountry": "Country:", + "LabelCriticRating": "Critic rating:", + "LabelCurrentPassword": "Current password:", + "LabelCurrentStatus": "Current status:", + "LabelCustomCertificatePath": "Custom SSL certificate path:", + "LabelCustomCertificatePathHelp": "Path to a PKCS #12 file containing a certificate and private key to enable TLS support on a custom domain.", + "LabelCustomCss": "Custom CSS:", + "LabelCustomCssHelp": "Apply your own custom styles on the web interface.", + "LabelCustomDeviceDisplayNameHelp": "Supply a custom display name or leave empty to use the name reported by the device.", + "LabelCustomRating": "Custom rating:", + "LabelDateAdded": "Date added:", + "LabelDateAddedBehavior": "Date added behavior for new content:", + "LabelDateAddedBehaviorHelp": "If a metadata value is present, it will always be used before either of these options.", + "LabelDateTimeLocale": "Date time locale:", + "LabelDay": "Day:", + "LabelDeathDate": "Death date:", + "LabelDefaultScreen": "Default screen:", + "LabelDefaultUser": "Default user:", + "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.", + "LabelDeinterlaceMethod": "Deinterlacing method:", + "LabelDeviceDescription": "Device description", + "LabelDidlMode": "DIDL mode:", + "LabelDiscNumber": "Disc number:", + "LabelDisplayLanguage": "Display language:", + "LabelDisplayLanguageHelp": "Translating Jellyfin is an ongoing project.", + "LabelDisplayMode": "Display mode:", + "LabelDisplayName": "Display name:", + "LabelDisplayOrder": "Display order:", + "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in", + "LabelDownMixAudioScale": "Audio boost when downmixing:", + "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. A value of one will preserve the original volume.", + "LabelDownloadLanguages": "Download languages:", + "LabelDropImageHere": "Drop image here, or click to browse.", + "LabelDroppedFrames": "Dropped frames:", + "LabelDropShadow": "Drop shadow:", + "LabelDynamicExternalId": "{0} Id:", + "LabelEasyPinCode": "Easy pin code:", + "LabelEmbedAlbumArtDidl": "Embed album art in Didl", + "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.", + "LabelEnableAutomaticPortMap": "Enable automatic port mapping", + "LabelEnableAutomaticPortMapHelp": "Automatically forward public ports on your router to local ports on your server via UPnP. This may not work with some router models or network configurations. Changes will not apply until after a server restart.", + "LabelEnableBlastAliveMessages": "Blast alive messages", + "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.", + "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval", + "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches.", + "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging", + "LabelEnableDlnaDebugLoggingHelp": "Create large log files and should only be used as needed for troubleshooting purposes.", + "LabelEnableDlnaPlayTo": "Enable DLNA Play To", + "LabelEnableDlnaPlayToHelp": "Detect devices within your network and offer the ability to control them remotely.", + "LabelEnableDlnaServer": "Enable DLNA server", + "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play content.", + "LabelEnableHardwareDecodingFor": "Enable hardware decoding for:", + "LabelEnableHttps": "Enable HTTPS", + "LabelEnableHttpsHelp": "Listen on the configured HTTPS port. A valid certificate must also be supplied for this to take effect.", + "LabelEnableRealtimeMonitor": "Enable real time monitoring", + "LabelEnableRealtimeMonitorHelp": "Changes to files will be processed immediately on supported file systems.", + "LabelEnableSingleImageInDidlLimit": "Limit to single embedded image", + "LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.", + "LabelEndDate": "End date:", + "LabelEpisodeNumber": "Episode number:", + "LabelEvent": "Event:", + "LabelEveryXMinutes": "Every:", + "LabelBaseUrl": "Base URL:", + "LabelBaseUrlHelp": "Add a custom subdirectory to the server URL. For example: http://example.com/<baseurl>", + "LabelExtractChaptersDuringLibraryScan": "Extract chapter images during the library scan", + "LabelExtractChaptersDuringLibraryScanHelp": "Generate chapter images when videos are imported during the library scan. Otherwise, they will be extracted during the chapter images scheduled task, allowing the regular library scan to complete faster.", + "LabelFailed": "Failed", + "LabelFileOrUrl": "File or URL:", + "LabelFinish": "Finish", + "LabelFolder": "Folder:", + "LabelFont": "Font:", + "LabelForgotPasswordUsernameHelp": "Enter your username, if you remember it.", + "LabelFormat": "Format:", + "LabelFriendlyName": "Friendly name:", + "LabelServerNameHelp": "This name will be used to identify the server and will default to the server's hostname.", + "LabelGroupMoviesIntoCollections": "Group movies into collections", + "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies in a collection will be displayed as one grouped item.", + "LabelH264Crf": "H264 encoding CRF:", + "LabelEncoderPreset": "H264 and H265 encoding preset:", + "LabelHardwareAccelerationType": "Hardware acceleration:", + "LabelHardwareAccelerationTypeHelp": "Hardware acceleration requires additional configuration.", + "LabelHomeNetworkQuality": "Home network quality:", + "LabelHomeScreenSectionValue": "Home screen section {0}:", + "LabelHttpsPort": "Local HTTPS port number:", + "LabelHttpsPortHelp": "The TCP port number for the HTTPS server.", + "LabelIconMaxResHelp": "Maximum resolution of icons exposed via the upnp:icon property.", + "LabelIconMaxHeight": "Icon maximum height:", + "LabelIconMaxWidth": "Icon maximum width:", + "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.", + "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.", + "LabelImageType": "Image type:", + "LabelImportOnlyFavoriteChannels": "Restrict to channels marked as favorite", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "Use the easy pin code to sign in to clients within your local network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", + "LabelInternetQuality": "Internet quality:", + "LabelKeepUpTo": "Keep up to:", + "LabelKnownProxies": "Known proxies:", + "LabelKidsCategories": "Children's categories:", + "LabelKodiMetadataDateFormat": "Release date format:", + "LabelKodiMetadataDateFormatHelp": "All dates within NFO files will be parsed using this format.", + "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart to extrathumbs field", + "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", + "LabelKodiMetadataEnablePathSubstitution": "Enable path substitution", + "LabelKodiMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.", + "LabelKodiMetadataSaveImagePaths": "Save image paths within nfo files", + "LabelKodiMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Kodi guidelines.", + "LabelKodiMetadataUser": "Save user watch data to NFO files for:", + "LabelKodiMetadataUserHelp": "Save watch data to NFO files for other applications to utilize.", + "LabelLanNetworks": "LAN networks:", + "LabelLanguage": "Language:", + "LabelLibraryPageSize": "Library page size:", + "LabelLibraryPageSizeHelp": "Sets the amount of items to show on a library page. Set to 0 in order to disable paging.", + "LabelLineup": "Lineup:", + "LabelLocalHttpServerPortNumber": "Local HTTP port number:", + "LabelLocalHttpServerPortNumberHelp": "The TCP port number for the HTTP server.", + "LabelLockItemToPreventChanges": "Lock this item to prevent future changes", + "LabelLoginDisclaimer": "Login disclaimer:", + "LabelLoginDisclaimerHelp": "A message that will be displayed at the bottom of the login page.", + "LabelLogs": "Logs:", + "LabelManufacturer": "Manufacturer:", + "LabelManufacturerUrl": "Manufacturer URL", + "LabelMatchType": "Match type:", + "LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:", + "LabelMaxChromecastBitrate": "Chromecast streaming quality:", + "LabelMaxParentalRating": "Maximum allowed parental rating:", + "LabelMaxResumePercentage": "Maximum resume percentage:", + "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time.", + "LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:", + "LabelMaxStreamingBitrate": "Maximum streaming quality:", + "LabelMaxStreamingBitrateHelp": "Specify a maximum bitrate when streaming.", + "LabelMessageText": "Message text:", + "LabelMessageTitle": "Message title:", + "LabelMetadata": "Metadata:", + "LabelMetadataDownloadLanguage": "Preferred download language:", + "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.", + "LabelMetadataReaders": "Metadata readers:", + "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.", + "LabelMetadataSavers": "Metadata savers:", + "LabelMetadataSaversHelp": "Choose the file formats to use when saving your metadata.", + "LabelMethod": "Method:", + "LabelMinBackdropDownloadWidth": "Minimum backdrop download width:", + "LabelMinResumeDuration": "Minimum resume duration:", + "LabelMinResumeDurationHelp": "The shortest video length in seconds that will save playback location and let you resume.", + "LabelMinResumePercentage": "Minimum resume percentage:", + "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time.", + "LabelMinScreenshotDownloadWidth": "Minimum screenshot download width:", + "LabelModelDescription": "Model description", + "LabelModelName": "Model name", + "LabelModelNumber": "Model number", + "LabelModelUrl": "Model URL", + "LabelMonitorUsers": "Monitor activity from:", + "LabelMovieCategories": "Movie categories:", + "LabelMoviePrefix": "Movie prefix:", + "LabelMoviePrefixHelp": "If a prefix is applied to movie titles, enter it here so the server can handle it properly.", + "LabelMovieRecordingPath": "Movie recording path:", + "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:", + "LabelMusicStreamingTranscodingBitrateHelp": "Specify a maximum bitrate when streaming music.", + "LabelName": "Name:", + "LabelChromecastVersion": "Chromecast Version", + "LabelStable": "Stable", + "LabelUnstable": "Unstable", + "LabelNewName": "New name:", + "LabelNewPassword": "New password:", + "LabelNewPasswordConfirm": "New password confirm:", + "LabelNewsCategories": "News categories:", + "LabelNotificationEnabled": "Enable this notification", + "LabelNumber": "Number:", + "LabelNumberOfGuideDays": "Number of days of guide data to download:", + "LabelNumberOfGuideDaysHelp": "Downloading more days worth of guide data provides the ability to schedule out further in advance and view more listings, but it will also take longer to download. Auto will choose based on the number of channels.", + "LabelOptionalNetworkPath": "Shared network folder:", + "LabelOptionalNetworkPathHelp": "If this folder is shared on your network, supplying the network share path can allow clients on other devices to access media files directly. For example, {0} or {1}.", + "LabelOriginalAspectRatio": "Original aspect ratio:", + "LabelOriginalTitle": "Original title:", + "LabelOverview": "Overview:", + "LabelParentNumber": "Parent number:", + "LabelParentalRating": "Parental rating:", + "LabelPassword": "Password:", + "LabelPasswordConfirm": "Password (confirm):", + "LabelPasswordResetProvider": "Password Reset Provider:", + "LabelPasswordRecoveryPinCode": "Pin code:", + "LabelPath": "Path:", + "LabelPersonRole": "Role:", + "LabelPersonRoleHelp": "Example: Ice cream truck driver", + "LabelPlaceOfBirth": "Place of birth:", + "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language", + "LabelPlayer": "Player:", + "LabelPlayerDimensions": "Player dimensions:", + "LabelPlaylist": "Playlist:", + "LabelPlayMethod": "Play method:", + "LabelPleaseRestart": "Changes will take effect after manually reloading the web client.", + "LabelPostProcessor": "Post-processing application:", + "LabelPostProcessorArguments": "Post-processor command line arguments:", + "LabelPostProcessorArgumentsHelp": "Use {path} as the path to the recording file.", + "LabelPreferredDisplayLanguage": "Preferred display language:", + "LabelPreferredSubtitleLanguage": "Preferred subtitle language:", + "LabelProfileAudioCodecs": "Audio codecs:", + "LabelProfileCodecs": "Codecs:", + "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.", + "LabelProfileContainer": "Container:", + "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.", + "LabelProfileVideoCodecs": "Video codecs:", + "LabelProtocol": "Protocol:", + "LabelProtocolInfo": "Protocol info:", + "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", + "LabelPublicHttpPort": "Public HTTP port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local HTTP port.", + "LabelPublicHttpsPort": "Public HTTPS port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local HTTPS port.", + "LabelQuickConnectCode": "Quick connect code:", + "LabelReasonForTranscoding": "Reason for transcoding:", + "LabelRecord": "Record:", + "LabelRecordingPath": "Default recording path:", + "LabelRecordingPathHelp": "Specify the default location to save recordings. If left empty, the server's program data folder will be used.", + "LabelRefreshMode": "Refresh mode:", + "LabelReleaseDate": "Release date:", + "LabelRemoteClientBitrateLimit": "Internet streaming bitrate limit (Mbps):", + "LabelRemoteClientBitrateLimitHelp": "An optional per-stream bitrate limit for all out of network devices. This is useful to prevent devices from requesting a higher bitrate than your internet connection can handle. This may result in increased CPU load on your server in order to transcode videos on the fly to a lower bitrate.", + "LabelRequireHttps": "Require HTTPS", + "LabelRequireHttpsHelp": "If checked, the server will automatically redirect all requests over HTTP to HTTPS. This has no effect if the server is not listening on HTTPS.", + "LabelRuntimeMinutes": "Runtime:", + "LabelSaveLocalMetadata": "Save artwork into media folders", + "LabelSaveLocalMetadataHelp": "Saving artwork into media folders will put them in a place where they can be easily edited.", + "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", + "LabelScreensaver": "Screensaver:", + "EnableFasterAnimations": "Faster animations", + "EnableFasterAnimationsHelp": "Use faster animations and transitions", + "LabelSeasonNumber": "Season number:", + "LabelSelectFolderGroups": "Automatically group content from the following folders into views such as Movies, Music and TV:", + "LabelSelectFolderGroupsHelp": "Folders that are unchecked will be displayed by themselves in their own view.", + "LabelSelectUsers": "Select users:", + "LabelSelectVersionToInstall": "Select version to install:", + "LabelSendNotificationToUsers": "Send the notification to:", + "LabelSerialNumber": "Serial number", + "LabelSeriesRecordingPath": "Series recording path:", + "LabelServerHost": "Host:", + "LabelServerHostHelp": "192.168.1.100:8096 or https://myserver.com", + "LabelServerName": "Server name:", + "LabelSimultaneousConnectionLimit": "Simultaneous stream limit:", + "LabelSize": "Size:", + "LabelSkipBackLength": "Skip back length:", + "LabelSkipForwardLength": "Skip forward length:", + "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language", + "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.", + "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains embedded subtitles", + "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery and decrease the likelihood of video transcoding.", + "LabelSonyAggregationFlags": "Sony aggregation flags:", + "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.", + "LabelSortBy": "Sort by:", + "LabelSortOrder": "Sort order:", + "LabelSortTitle": "Sort title:", + "LabelSource": "Source:", + "LabelSpecialSeasonsDisplayName": "Special season display name:", + "LabelSportsCategories": "Sports categories:", + "LabelStartWhenPossible": "Start when possible:", + "LabelStatus": "Status:", + "LabelStopWhenPossible": "Stop when possible:", + "LabelStopping": "Stopping", + "LabelStreamType": "Stream type:", + "LabelSubtitleDownloaders": "Subtitle downloaders:", + "LabelSubtitleFormatHelp": "Example: srt", + "LabelSubtitlePlaybackMode": "Subtitle mode:", + "LabelSupportedMediaTypes": "Supported Media Types:", + "LabelSyncPlayTimeOffset": "Time offset with the server:", + "MillisecondsUnit": "ms", + "LabelSyncPlayPlaybackDiff": "Playback time difference:", + "LabelSyncPlaySyncMethod": "Sync method:", + "LabelSyncPlayNewGroup": "New group", + "LabelSyncPlayNewGroupDescription": "Create a new group", + "LabelSyncPlayLeaveGroup": "Leave group", + "LabelSyncPlayLeaveGroupDescription": "Disable SyncPlay", + "LabelSyncPlayAccessCreateAndJoinGroups": "Allow user to create and join groups", + "LabelSyncPlayAccessJoinGroups": "Allow user to join groups", + "LabelSyncPlayAccessNone": "Disabled for this user", + "LabelSyncPlayAccess": "SyncPlay access", + "LabelTVHomeScreen": "TV mode home screen:", + "LabelTag": "Tag:", + "LabelTagline": "Tagline:", + "LabelTextBackgroundColor": "Text background color:", + "LabelTextColor": "Text color:", + "LabelTextSize": "Text size:", + "LabelTheme": "Theme:", + "LabelTime": "Time:", + "LabelTimeLimitHours": "Time limit (hours):", + "LabelTitle": "Title:", + "LabelTrackNumber": "Track number:", + "LabelTranscodePath": "Transcode path:", + "LabelTranscodingTempPathHelp": "Specify a custom path for the transcode files served to clients. Leave blank to use the server default.", + "LabelTranscodes": "Transcodes:", + "LabelTranscodingFramerate": "Transcoding framerate:", + "LabelTranscodingProgress": "Transcoding progress:", + "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.", + "LabelTriggerType": "Trigger Type:", + "LabelTunerIpAddress": "Tuner IP Address:", + "LabelTunerType": "Tuner type:", + "LabelType": "Type:", + "LabelTypeMetadataDownloaders": "{0} metadata downloaders:", + "LabelTypeText": "Text", + "LabelUseNotificationServices": "Use the following services:", + "LabelUser": "User:", + "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 login attempts before user is locked out:", + "LabelUserMaxActiveSessions": "Maximum number of simultaneous user sessions:", + "LabelUserRemoteClientBitrateLimitHelp": "Override the default global value set in server playback settings.", + "LabelUsername": "Username:", + "LabelVaapiDevice": "VA API Device:", + "LabelVaapiDeviceHelp": "This is the render node that is used for hardware acceleration.", + "LabelValue": "Value:", + "LabelVersion": "Version:", + "LabelVersionInstalled": "{0} installed", + "DashboardVersionNumber": "Version: {0}", + "DashboardServerName": "Server: {0}", + "DashboardOperatingSystem": "Operating System: {0}", + "DashboardArchitecture": "Architecture: {0}", + "LabelVideoBitrate": "Video bitrate:", + "LabelVideoCodec": "Video codec:", + "LabelVideoResolution": "Video resolution:", + "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:", + "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.", + "LabelYear": "Year:", + "LabelYoureDone": "You're Done!", + "LabelZipCode": "Zip Code:", + "LabelffmpegPath": "FFmpeg path:", + "LabelffmpegPathHelp": "The path to the ffmpeg application file or folder containing ffmpeg.", + "LanNetworksHelp": "Comma separated list of IP addresses or IP/netmask entries for networks that will be considered on local network when enforcing bandwidth restrictions. If set, all other IP addresses will be considered to be on the external network and will be subject to the external bandwidth restrictions. If left blank, only the server's subnet is considered to be on the local network.", + "Large": "Large", + "LatestFromLibrary": "Latest {0}", + "LearnHowYouCanContribute": "Learn how you can contribute.", + "LeaveBlankToNotSetAPassword": "You can leave this field blank to set no password.", + "LibraryAccessHelp": "Select the libraries to share with this user. Administrators will be able to edit all folders using the metadata manager.", + "List": "List", + "Live": "Live", + "LiveBroadcasts": "Live broadcasts", + "LiveTV": "Live TV", + "Logo": "Logo", + "ManageLibrary": "Manage library", + "ManageRecording": "Manage recording", + "MapChannels": "Map Channels", + "MarkPlayed": "Mark played", + "MarkUnplayed": "Mark unplayed", + "MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.", + "MediaInfoAnamorphic": "Anamorphic", + "MediaInfoAspectRatio": "Aspect ratio", + "MediaInfoBitDepth": "Bit depth", + "MediaInfoBitrate": "Bitrate", + "MediaInfoChannels": "Channels", + "MediaInfoCodec": "Codec", + "MediaInfoCodecTag": "Codec tag", + "MediaInfoContainer": "Container", + "MediaInfoDefault": "Default", + "MediaInfoExternal": "External", + "MediaInfoForced": "Forced", + "MediaInfoFramerate": "Framerate", + "MediaInfoInterlaced": "Interlaced", + "MediaInfoLanguage": "Language", + "MediaInfoLayout": "Layout", + "MediaInfoLevel": "Level", + "MediaInfoPath": "Path", + "MediaInfoPixelFormat": "Pixel format", + "MediaInfoProfile": "Profile", + "MediaInfoRefFrames": "Ref frames", + "MediaInfoResolution": "Resolution", + "MediaInfoSampleRate": "Sample rate", + "MediaInfoSize": "Size", + "MediaInfoTimestamp": "Timestamp", + "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.", + "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?", + "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?", + "MessageConfirmAppExit": "Do you want to exit?", + "MessageConfirmDeleteGuideProvider": "Are you sure you wish to delete this guide provider?", + "MessageConfirmDeleteTunerDevice": "Are you sure you wish to delete this device?", + "MessageConfirmProfileDeletion": "Are you sure you wish to delete this profile?", + "MessageConfirmRecordingCancellation": "Cancel recording?", + "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?", + "MessageConfirmRestart": "Are you sure you wish to restart Jellyfin?", + "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this API key? The application's connection to this server will be abruptly terminated.", + "MessageConfirmShutdown": "Are you sure you wish to shutdown the server?", + "MessageContactAdminToResetPassword": "Please contact your system administrator to reset your password.", + "MessageCreateAccountAt": "Create an account at {0}", + "MessageDeleteTaskTrigger": "Are you sure you wish to delete this task trigger?", + "MessageDirectoryPickerBSDInstruction": "For BSD, you may need to configure storage within your FreeNAS Jail so Jellyfin can access your media.", + "MessageDirectoryPickerLinuxInstruction": "For Linux on Arch Linux, CentOS, Debian, Fedora, openSUSE, or Ubuntu, you must grant the service user at least read access to your storage locations.", + "MessageDownloadQueued": "Download queued.", + "MessageEnablingOptionLongerScans": "Enabling this option may result in significantly longer library scans.", + "MessageFileReadError": "There was an error reading the file. Please try again.", + "MessageForgotPasswordFileCreated": "The following file has been created on your server and contains instructions on how to proceed:", + "MessageForgotPasswordInNetworkRequired": "Please try again within your home network to initiate the password reset process.", + "MessageImageFileTypeAllowed": "Only JPEG and PNG files are supported.", + "MessageImageTypeNotSelected": "Please select an image type from the drop-down menu.", + "MessageInvalidForgotPasswordPin": "An invalid or expired pin code was entered. Please try again.", + "MessageInvalidUser": "Invalid username or password. Please try again.", + "MessageItemSaved": "Item saved.", + "MessageItemsAdded": "Items added.", + "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item or the global default value.", + "MessageNoAvailablePlugins": "No available plugins.", + "MessageNoRepositories": "No repositories.", + "HeaderNewRepository": "New Repository", + "LabelRepositoryUrl": "Repository URL", + "LabelRepositoryUrlHelp": "The location of the repository manifest you want to include.", + "LabelRepositoryName": "Repository Name", + "LabelRepositoryNameHelp": "A custom name to distinguish this repository from any others added to your server.", + "MessageAddRepository": "If you wish to add a repository, click the button next to the header and fill out the requested information.", + "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, and Albums. Click the + button to start creating collections.", + "MessageNoGenresAvailable": "Enable some metadata providers to pull genres from the internet.", + "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.", + "MessageNoServersAvailable": "No servers have been found using the automatic server discovery.", + "MessageNoTrailersFound": "Install the trailers 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 codes that were used to perform the reset.", + "MessagePlayAccessRestricted": "Playback of this content is currently restricted. Please contact your server administrator for more information.", + "MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.", + "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 community members are a great way to enhance your experience with additional features and benefits. Before installing, please be aware of the effects they may have on your server, such as longer library scans, additional background processing, and decreased system stability.", + "MessageReenableUser": "See below to reenable", + "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:", + "MessageUnableToConnectToServer": "We're unable to connect to the selected server right now. Please ensure it is running and try again.", + "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders.", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageSyncPlayEnabled": "SyncPlay enabled.", + "MessageSyncPlayDisabled": "SyncPlay disabled.", + "MessageSyncPlayUserJoined": "{0} has joined the group.", + "MessageSyncPlayUserLeft": "{0} has left the group.", + "MessageSyncPlayGroupWait": "{0} is buffering…", + "MessageSyncPlayNoGroupsAvailable": "No groups available. Start playing something first.", + "MessageSyncPlayPlaybackPermissionRequired": "Playback permission required.", + "MessageSyncPlayGroupDoesNotExist": "Failed to join group because it does not exist.", + "MessageSyncPlayCreateGroupDenied": "Permission required to create a group.", + "MessageSyncPlayJoinGroupDenied": "Permission required to use SyncPlay.", + "MessageSyncPlayLibraryAccessDenied": "Access to this content is restricted.", + "MessageSyncPlayErrorAccessingGroups": "An error occurred while accessing groups list.", + "MessageSyncPlayErrorNoActivePlayer": "No active player found. SyncPlay has been disabled.", + "MessageSyncPlayErrorMissingSession": "Failed to enable SyncPlay! Missing session.", + "MessageSyncPlayErrorMedia": "Failed to enable SyncPlay! Media error.", + "Metadata": "Metadata", + "MetadataManager": "Metadata Manager", + "MetadataSettingChangeHelp": "Changing metadata settings will affect new content added going forward. To refresh existing content, open the detail screen and click the refresh button, or perform bulk refreshes using the metadata manager.", + "MinutesAfter": "minutes after", + "MinutesBefore": "minutes before", + "Mobile": "Mobile", + "Monday": "Monday", + "MoreFromValue": "More from {0}", + "MoreUsersCanBeAddedLater": "More users can be added later from within the dashboard.", + "MoreMediaInfo": "Media Info", + "MoveLeft": "Move left", + "MoveRight": "Move right", + "MovieLibraryHelp": "Review the {0}movie naming guide{1}.", + "Movie": "Movie", + "Movies": "Movies", + "MusicAlbum": "Music Album", + "MusicArtist": "Music Artist", + "MusicLibraryHelp": "Review the {0}music naming guide{1}.", + "MusicVideo": "Music Video", + "MusicVideos": "Music Videos", + "Mute": "Mute", + "MySubtitles": "My Subtitles", + "Name": "Name", + "Never": "Never", + "NewCollection": "New Collection", + "NewCollectionHelp": "Collections allow you to create personalized groupings of movies and other library content.", + "NewCollectionNameExample": "Example: Star Wars Collection", + "NewEpisodes": "New episodes", + "NewEpisodesOnly": "New episodes only", + "News": "News", + "Next": "Next", + "NextTrack": "Skip to next", + "NextUp": "Next Up", + "No": "No", + "NoCreatedLibraries": "Seems like you haven't created any libraries yet. {0}Would you like to create one now?{1}", + "NoNewDevicesFound": "No new devices found. To add a new tuner, close this dialog and enter the device information manually.", + "MessageNoNextUpItems": "None found. Start watching your shows!", + "MessageNoPluginConfiguration": "This plugin has no settings to configure.", + "NoSubtitleSearchResultsFound": "No results found.", + "NoSubtitlesHelp": "Subtitles will not be loaded by default. They can still be turned on manually during playback.", + "None": "None", + "Normal": "Normal", + "NumLocationsValue": "{0} folders", + "Off": "Off", + "OneChannel": "One channel", + "OnlyForcedSubtitles": "Only Forced", + "OnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.", + "OnlyImageFormats": "Only Image Formats (VOBSUB, PGS, SUB)", + "Option3D": "3D", + "OptionAdminUsers": "Administrators", + "OptionAllUsers": "All users", + "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding", + "OptionForceRemoteSourceTranscoding": "Force transcoding of remote media sources (like LiveTV)", + "OptionAllowBrowsingLiveTv": "Allow Live TV access", + "OptionAllowContentDownloading": "Allow media downloading and syncing", + "OptionAllowLinkSharing": "Allow social media sharing", + "OptionAllowLinkSharingHelp": "Only web pages containing media information are shared. Media files are never shared publicly. Shares are time-limited and will expire after {0} days.", + "OptionAllowManageLiveTv": "Allow Live TV recording management", + "OptionAllowMediaPlayback": "Allow media playback", + "OptionAllowMediaPlaybackTranscodingHelp": "Restricting access to transcoding may cause playback failures in clients due to unsupported media formats.", + "OptionAllowRemoteControlOthers": "Allow remote control of other users", + "OptionAllowRemoteSharedDevices": "Allow remote control of shared devices", + "OptionAllowRemoteSharedDevicesHelp": "DLNA devices are considered shared until a user begins controlling them.", + "OptionAllowSyncTranscoding": "Allow media downloading and syncing that requires transcoding", + "OptionAllowUserToManageServer": "Allow this user to manage the server", + "OptionAllowVideoPlaybackRemuxing": "Allow video playback that requires conversion without re-encoding", + "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding", + "OptionAutomaticallyGroupSeries": "Automatically merge series that are spread across multiple folders", + "OptionAutomaticallyGroupSeriesHelp": "Series that are spread across multiple folders within this library will be automatically merged into a single series.", + "OptionBluray": "Blu-ray", + "OptionCaptionInfoExSamsung": "CaptionInfoEx (Samsung)", + "OptionCommunityRating": "Community Rating", + "OptionCriticRating": "Critic Rating", + "OptionCustomUsers": "Custom", + "OptionDaily": "Daily", + "OptionDateAdded": "Date Added", + "OptionDateAddedFileTime": "Use file creation date", + "OptionDateAddedImportTime": "Use date scanned into the library", + "OptionDatePlayed": "Date Played", + "OptionDisableUser": "Disable this user", + "OptionDisableUserHelp": "The server will not allow any connections from this user. Existing connections will be abruptly terminated.", + "OptionDislikes": "Dislikes", + "OptionDisplayFolderView": "Display a folder view to show plain media folders", + "OptionDisplayFolderViewHelp": "Display folders alongside your other media libraries. This can be useful if you'd like to have a plain folder view.", + "OptionDownloadImagesInAdvance": "Download images in advance", + "OptionDownloadImagesInAdvanceHelp": "By default, most images are only downloaded when requested by a client. Enable this option to download all images in advance, as new media is imported. This may cause significantly longer library scans.", + "OptionDvd": "DVD", + "OptionEmbedSubtitles": "Embed within container", + "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", + "OptionEnableExternalContentInSuggestions": "Enable external content in suggestions", + "OptionEnableExternalContentInSuggestionsHelp": "Allow internet trailers and live TV programs to be included within suggested content.", + "OptionEnableForAllTuners": "Enable for all tuner devices", + "OptionEnableM2tsMode": "Enable M2ts mode", + "OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.", + "OptionEquals": "Equals", + "OptionEstimateContentLength": "Estimate content length when transcoding", + "OptionEveryday": "Every day", + "OptionExternallyDownloaded": "External download", + "OptionExtractChapterImage": "Enable chapter image extraction", + "OptionHasThemeSong": "Theme Song", + "OptionHasThemeVideo": "Theme Video", + "OptionHideUser": "Hide this user from login screens", + "OptionHideUserFromLoginHelp": "Useful for private or hidden administrator accounts. The user will need to sign in manually by entering their username and password.", + "OptionHlsSegmentedSubtitles": "HLS segmented subtitles", + "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests", + "OptionIgnoreTranscodeByteRangeRequestsHelp": "These requests will be honored but will ignore the byte range header.", + "OptionImdbRating": "IMDb Rating", + "OptionIsHD": "HD", + "OptionIsSD": "SD", + "OptionLikes": "Likes", + "OptionLoginAttemptsBeforeLockout": "Determines how many incorrect login attempts can be made before lockout occurs.", + "OptionLoginAttemptsBeforeLockoutHelp": "A value of zero means inheriting the default of three attempts for normal users and five for administrators. Setting this to -1 will disable the feature.", + "OptionMaxActiveSessions": "Sets the maximum number of simultaneous user sessions.", + "OptionMaxActiveSessionsHelp": "A value of 0 will disable the feature.", + "OptionMax": "Max", + "OptionMissingEpisode": "Missing Episodes", + "OptionNew": "New…", + "OptionOnInterval": "On an interval", + "OptionParentalRating": "Parental Rating", + "OptionPlainStorageFolders": "Display all folders as plain storage folders", + "OptionPlainStorageFoldersHelp": "All folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".", + "OptionPlainVideoItems": "Display all videos as plain video items", + "OptionPlainVideoItemsHelp": "All videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".", + "OptionPlayCount": "Play Count", + "OptionPremiereDate": "Premiere Date", + "OptionProtocolHls": "HTTP Live Streaming", + "OptionProtocolHttp": "HTTP", + "OptionRandom": "Random", + "OptionRegex": "Regex", + "OptionReleaseDate": "Release Date", + "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding", + "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.", + "OptionRequirePerfectSubtitleMatch": "Only download subtitles that are a perfect match for my video files", + "OptionRequirePerfectSubtitleMatchHelp": "Requiring a perfect match will filter subtitles to include only those that have been tested and verified with your exact video file. Unchecking this will increase the likelihood of subtitles being downloaded, but will increase the chances of mistimed or incorrect subtitle text.", + "OptionResElement": "res element", + "OptionResumable": "Resumable", + "OptionSaveMetadataAsHidden": "Save metadata and images as hidden files", + "OptionSaveMetadataAsHiddenHelp": "Changing this will apply to new metadata saved going forward. Existing metadata files will be updated the next time they are saved by the server.", + "OptionSpecialEpisode": "Specials", + "OptionSubstring": "Substring", + "OptionTrackName": "Track Name", + "OptionTvdbRating": "TVDB Rating", + "OptionUnairedEpisode": "Unaired Episodes", + "OptionWakeFromSleep": "Wake from sleep", + "OptionWeekdays": "Weekdays", + "OptionWeekends": "Weekends", + "OptionWeekly": "Weekly", + "OriginalAirDateValue": "Original air date: {0}", + "Overview": "Overview", + "PackageInstallCancelled": "{0} (version {1}) installation cancelled.", + "PackageInstallCompleted": "{0} (version {1}) installation completed.", + "PackageInstallFailed": "{0} (version {1}) installation failed.", + "ParentalRating": "Parental rating", + "PasswordMatchError": "Password and password confirmation must match.", + "PasswordResetComplete": "The password has been reset.", + "PasswordResetConfirmation": "Are you sure you wish to reset the 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", + "Person": "Person", + "Photos": "Photos", + "Photo": "Photo", + "PictureInPicture": "Picture in picture", + "PinCodeResetComplete": "The pin code has been reset.", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "PlaceFavoriteChannelsAtBeginning": "Place favorite channels at the beginning", + "Play": "Play", + "PlayAllFromHere": "Play all from here", + "PlaybackData": "Playback Data", + "PlaybackRate": "Playback Rate", + "PlayCount": "Play count", + "PlayFromBeginning": "Play from beginning", + "PlayNext": "Play next", + "PlayNextEpisodeAutomatically": "Play next episode automatically", + "PlaybackErrorNoCompatibleStream": "This client isn't compatible with the media and the server isn't sending a compatible media format.", + "Played": "Played", + "Playlists": "Playlists", + "PleaseAddAtLeastOneFolder": "Please add at least one folder to this library by clicking the Add button.", + "PleaseConfirmPluginInstallation": "Please click OK to confirm you've read the above and wish to proceed with the plugin installation.", + "PleaseEnterNameOrId": "Please enter a name or an external ID.", + "PleaseRestartServerName": "Please restart Jellyfin on {0}.", + "PleaseSelectTwoItems": "Please select at least two items.", + "Poster": "Poster", + "PosterCard": "Poster Card", + "MessagePluginInstalled": "The plugin has been successfully installed. The server will need to be restarted for changes to take effect.", + "MessagePluginInstallError": "An error occured while installing the plugin.", + "MessageGetInstalledPluginsError": "An error occured while getting the list of currently installed plugins.", + "PreferEmbeddedTitlesOverFileNames": "Prefer embedded titles over filenames", + "PreferEmbeddedTitlesOverFileNamesHelp": "This determines the default display title when no internet metadata or local metadata is available.", + "PreferEmbeddedEpisodeInfosOverFileNamesHelp": "This uses the episode information from the embedded metadata if available.", + "PreferEmbeddedEpisodeInfosOverFileNames": "Prefer embedded episode information over filenames", + "Premiere": "Premiere", + "Premieres": "Premieres", + "Previous": "Previous", + "PreviousTrack": "Skip to previous", + "Primary": "Primary", + "Producer": "Producer", + "ProductionLocations": "Production locations", + "Profile": "Profile", + "Programs": "Programs", + "Quality": "Quality", + "QuickConnect": "Quick Connect", + "QuickConnectActivationSuccessful": "Successfully activated", + "QuickConnectAuthorizeCode": "Enter code {0} to login", + "QuickConnectAuthorizeSuccess": "Request authorized", + "QuickConnectAuthorizeFail": "Unknown quick connect code", + "QuickConnectDeactivated": "Quick connect was deactivated before the login request could be approved", + "QuickConnectDescription": "To sign in with quick connect, select the Quick Connect button on the device you are logging in from and enter the displayed code below.", + "QuickConnectInvalidCode": "Invalid quick connect code", + "QuickConnectNotAvailable": "Ask your server administrator to enable quick connect", + "QuickConnectNotActive": "Quick connect is not active on this server", + "Raised": "Raised", + "Rate": "Rate", + "RecentlyWatched": "Recently watched", + "RecommendationBecauseYouLike": "Because you like {0}", + "RecommendationBecauseYouWatched": "Because you watched {0}", + "RecommendationDirectedBy": "Directed by {0}", + "RecommendationStarring": "Starring {0}", + "Record": "Record", + "RecordSeries": "Record series", + "RecordingCancelled": "Recording cancelled.", + "MessageChangeRecordingPath": "Changing your recording folder will not migrate existing recordings from the old location to the new. You'll need to move them manually if desired.", + "RecordingScheduled": "Recording scheduled.", + "Recordings": "Recordings", + "Refresh": "Refresh", + "RefreshDialogHelp": "Metadata is refreshed based on settings and internet services that are enabled in the dashboard.", + "RefreshMetadata": "Refresh metadata", + "RefreshQueued": "Refresh queued.", + "ReleaseDate": "Release date", + "RememberMe": "Remember Me", + "RemoveFromCollection": "Remove from collection", + "RemoveFromPlaylist": "Remove from playlist", + "Repeat": "Repeat", + "RepeatAll": "Repeat all", + "RepeatEpisodes": "Repeat episodes", + "RepeatMode": "Repeat Mode", + "RepeatOne": "Repeat one", + "ReplaceAllMetadata": "Replace all metadata", + "ReplaceExistingImages": "Replace existing images", + "ResetPassword": "Reset Password", + "Restart": "Restart", + "ResumeAt": "Resume from {0}", + "Rewind": "Rewind", + "Runtime": "Runtime", + "Saturday": "Saturday", + "Save": "Save", + "SaveChanges": "Save changes", + "SaveSubtitlesIntoMediaFolders": "Save subtitles into media folders", + "SaveSubtitlesIntoMediaFoldersHelp": "Storing subtitles next to video files will allow them to be more easily managed.", + "ScanForNewAndUpdatedFiles": "Scan for new and updated files", + "ScanLibrary": "Scan library", + "Schedule": "Schedule", + "Screenshot": "Screenshot", + "Screenshots": "Screenshots", + "Search": "Search", + "SearchForCollectionInternetMetadata": "Search the internet for artwork and metadata", + "SearchForMissingMetadata": "Search for missing metadata", + "SearchForSubtitles": "Search for Subtitles", + "SearchResults": "Search Results", + "Season": "Season", + "SelectAdminUsername": "Please select a username for the admin account.", + "SelectServer": "Select Server", + "SendMessage": "Send message", + "Series": "Series", + "SeriesCancelled": "Series cancelled.", + "SeriesDisplayOrderHelp": "Order episodes by air date, DVD order, or absolute numbering.", + "SeriesRecordingScheduled": "Series recording scheduled.", + "SeriesSettings": "Series settings", + "SeriesYearToPresent": "{0} - Present", + "ServerNameIsRestarting": "The server at {0} is restarting.", + "ServerNameIsShuttingDown": "The server at {0} is shutting down.", + "ServerRestartNeededAfterPluginInstall": "Jellyfin will need to be restarted after installing a plugin.", + "ServerUpdateNeeded": "This server needs to be updated. To download the latest version, please visit {0}", + "Settings": "Settings", + "SettingsSaved": "Settings saved.", + "SettingsWarning": "Changing these values may cause instability or connectivity failures. If you experience any problems, we recommend changing them back to default.", + "Share": "Share", + "ShowAdvancedSettings": "Show advanced settings", + "ShowIndicatorsFor": "Show indicators for:", + "ShowLess": "Show less", + "ShowMore": "Show more", + "ShowTitle": "Show title", + "ShowYear": "Show year", + "Shows": "Shows", + "Shuffle": "Shuffle", + "New": "New", + "Filter": "Filter", + "SimultaneousConnectionLimitHelp": "The maximum number of allowed simultaneous streams. Enter 0 for no limit.", + "SkipEpisodesAlreadyInMyLibrary": "Don't record episodes that are already in my library", + "SkipEpisodesAlreadyInMyLibraryHelp": "Episodes will be compared using season and episode numbers, when available.", + "Small": "Small", + "SmallCaps": "Small Caps", + "Smaller": "Smaller", + "Smart": "Smart", + "SmartSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.", + "Songs": "Songs", + "Sort": "Sort", + "SortByValue": "Sort by {0}", + "SortChannelsBy": "Sort channels by:", + "SortName": "Sort name", + "SpecialFeatures": "Special Features", + "Sports": "Sports", + "StopRecording": "Stop recording", + "Studios": "Studios", + "SubtitleAppearanceSettingsAlsoPassedToCastDevices": "These settings also apply to any Chromecast playback started by this device.", + "SubtitleAppearanceSettingsDisclaimer": "These settings will not apply to graphical subtitles (PGS, DVD, etc) or ASS/SSA subtitles that embed their own styles.", + "SubtitleDownloadersHelp": "Enable and rank your preferred subtitle downloaders in order of priority.", + "SubtitleOffset": "Subtitle Offset", + "Subtitle": "Subtitle", + "Subtitles": "Subtitles", + "Suggestions": "Suggestions", + "Sunday": "Sunday", + "Sync": "Sync", + "SyncPlayAccessHelp": "Select the level of access this user has to the SyncPlay feature. SyncPlay enables to sync playback with other devices.", + "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.", + "TV": "TV", + "TabAccess": "Access", + "TabAdvanced": "Advanced", + "TabCatalog": "Catalog", + "TabRepositories": "Repositories", + "TabCodecs": "Codecs", + "TabContainers": "Containers", + "TabDashboard": "Dashboard", + "TabDirectPlay": "Direct Play", + "TabLatest": "Latest", + "TabLogs": "Logs", + "TabMusic": "Music", + "TabMyPlugins": "My Plugins", + "TabNetworks": "Networks", + "TabNetworking": "Networking", + "TabNfoSettings": "NFO Settings", + "TabNotifications": "Notifications", + "TabOther": "Other", + "TabParentalControl": "Parental Control", + "TabPlugins": "Plugins", + "TabProfiles": "Profiles", + "TabResponses": "Responses", + "TabScheduledTasks": "Scheduled Tasks", + "TabServer": "Server", + "TabStreaming": "Streaming", + "TabUpcoming": "Upcoming", + "Tags": "Tags", + "TagsValue": "Tags: {0}", + "TellUsAboutYourself": "Tell us about yourself", + "ThemeSongs": "Theme songs", + "ThemeVideos": "Theme videos", + "TheseSettingsAffectSubtitlesOnThisDevice": "These settings affect subtitles on this device", + "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process. To begin, please select your preferred language.", + "Thumb": "Thumb", + "ThumbCard": "Thumb Card", + "Thursday": "Thursday", + "TitleHardwareAcceleration": "Hardware Acceleration", + "TitleHostingSettings": "Hosting Settings", + "TitlePlayback": "Playback", + "TrackCount": "{0} tracks", + "Trailers": "Trailers", + "Transcoding": "Transcoding", + "Tuesday": "Tuesday", + "TvLibraryHelp": "Review the {0}TV naming guide{1}.", + "UseDoubleRateDeinterlacing": "Double the frame rate when deinterlacing", + "UseDoubleRateDeinterlacingHelp": "This setting uses the field rate when deinterlacing, often referred to as bob deinterlacing, which doubles the frame rate of the video to provide full motion like what you would see when viewing interlaced video on a TV.", + "Uniform": "Uniform", + "UninstallPluginConfirmation": "Are you sure you wish to uninstall {0}?", + "HeaderUninstallPlugin": "Uninstall Plugin", + "Unmute": "Unmute", + "Unplayed": "Unplayed", + "Unrated": "Unrated", + "Up": "Up", + "Upload": "Upload", + "UserAgentHelp": "Supply a custom user-agent HTTP header.", + "UserProfilesIntro": "Jellyfin includes support for user profiles with granular display settings, play state, and parental controls.", + "ValueAlbumCount": "{0} albums", + "ValueAudioCodec": "Audio Codec: {0}", + "ValueCodec": "Codec: {0}", + "ValueConditions": "Conditions: {0}", + "ValueContainer": "Container: {0}", + "ValueDiscNumber": "Disc {0}", + "ValueEpisodeCount": "{0} episodes", + "ValueMinutes": "{0} min", + "ValueMovieCount": "{0} movies", + "ValueMusicVideoCount": "{0} music videos", + "ValueOneAlbum": "1 album", + "ValueOneEpisode": "1 episode", + "ValueOneMovie": "1 movie", + "ValueOneMusicVideo": "1 music video", + "ValueOneSeries": "1 series", + "ValueOneSong": "1 song", + "ValueSeconds": "{0} seconds", + "ValueSeriesCount": "{0} series", + "ValueSongCount": "{0} songs", + "ValueSpecialEpisodeName": "Special - {0}", + "ValueTimeLimitMultiHour": "Time limit: {0} hours", + "ValueTimeLimitSingleHour": "Time limit: 1 hour", + "ValueVideoCodec": "Video Codec: {0}", + "Vertical": "Vertical", + "Video": "Video", + "VideoAudio": "Video Audio", + "ViewAlbum": "View album", + "ViewAlbumArtist": "View album artist", + "ViewPlaybackInfo": "View playback info", + "Watched": "Watched", + "Wednesday": "Wednesday", + "WelcomeToProject": "Welcome to Jellyfin!", + "Whitelist": "Whitelist", + "WizardCompleted": "That's all we need for now. Jellyfin has begun collecting information about your media library. Check out some of our apps, and then click Finish to view the Dashboard.", + "Writer": "Writer", + "Writers": "Writers", + "XmlDocumentAttributeListHelp": "These attributes are applied to the root element of every XML response.", + "XmlTvKidsCategoriesHelp": "Programs with these categories will be displayed as programs for children. Separate multiple with '|'.", + "XmlTvMovieCategoriesHelp": "Programs with these categories will be displayed as movies. Separate multiple with '|'.", + "XmlTvNewsCategoriesHelp": "Programs with these categories will be displayed as news programs. Separate multiple with '|'.", + "XmlTvPathHelp": "A path to a XMLTV file. Jellyfin will read this file and periodically check it for updates. You are responsible for creating and updating the file.", + "XmlTvSportsCategoriesHelp": "Programs with these categories will be displayed as sports programs. Separate multiple with '|'.", + "Yadif": "YADIF", + "Bwdif": "BWDIF", + "Yes": "Yes", + "Yesterday": "Yesterday", + "PathNotFound": "The path could not be found. Please ensure the path is valid and try again.", + "WriteAccessRequired": "Jellyfin requires write access to this folder. Please ensure write access and try again.", + "ListPaging": "{0}-{1} of {2}", + "PersonRole": "as {0}", + "LastSeen": "Last seen {0}", + "DailyAt": "Daily at {0}", + "WeeklyAt": "{0}s at {1}", + "OnWakeFromSleep": "On wake from sleep", + "EveryXMinutes": "Every {0} minutes", + "EveryHour": "Every hour", + "EveryXHours": "Every {0} hours", + "OnApplicationStartup": "On application startup", + "UnsupportedPlayback": "Jellyfin cannot decrypt content protected by DRM but all content will be attempted regardless, including protected titles. Some files may appear completely black due to encryption or other unsupported features, such as interactive titles.", + "EnableBlurHash": "Enable blurred placeholders for images", + "EnableBlurHashHelp": "Images that are still being loaded will be displayed with a unique placeholder.", + "ButtonSyncPlay": "SyncPlay", + "ButtonCast": "Cast", + "ButtonPlayer": "Player", + "MediaInfoVideoRange": "Video range", + "MediaInfoColorSpace": "Color space", + "MediaInfoColorTransfer": "Color transfer", + "MediaInfoColorPrimaries": "Color primaries", + "LabelVideoRange": "Video range:", + "LabelColorSpace": "Color space:", + "LabelColorTransfer": "Color transfer:", + "LabelColorPrimaries": "Color primaries:", + "LabelOpenclDevice": "OpenCL Device:", + "LabelOpenclDeviceHelp": "This is the OpenCL device that is used for tonemapping. The left side of the dot is the platform number, and the right side is the device number on the platform. The default value is 0.0. The ffmpeg application file containing the OpenCL hardware acceleration method is required.", + "EnableTonemapping": "Enable Tone mapping", + "AllowTonemappingHelp": "Tone mapping can transform the dynamic range of a video from HDR to SDR while maintaining image details and colors, which are very important information for representing the original scene. Currently works only when transcoding videos with embedded HDR10 or HLG metadata. If the playback is not smooth or fails, please consider turning off the corresponding hardware decoder.", + "LabelTonemappingAlgorithm": "Select the Tone mapping algorithm to use:", + "TonemappingAlgorithmHelp": "Tone mapping can be fine-tuned. If you are not familiar with these options, just keep the default. The recommended value is Reinhard.", + "LabelTonemappingRange": "Tonemapping range:", + "TonemappingRangeHelp": "Select the output color range. Auto is the same as the input range.", + "LabelTonemappingDesat": "Tonemapping desat:", + "LabelTonemappingDesatHelp": "Apply desaturation for highlights that exceed this level of brightness. The higher the parameter, the more color information will be preserved. This setting helps prevent unnaturally blown-out colors for super-highlights, by (smoothly) turning into white instead. This makes images feel more natural, at the cost of reducing information about out-of-range colors. The recommended and default values are 0 and 0.5.", + "LabelTonemappingThreshold": "Tonemapping threshold:", + "LabelTonemappingThresholdHelp": "The tonemapping algorithm parameters is fine-tuned per each scene. And a threshold is used to detect whether the scene has changed or not. If the distance between the current frame average brightness and the current running average exceeds a threshold value, we would re-calculate scene average and peak brightness. The recommended and default values are 0.8 and 0.2.", + "LabelTonemappingPeak": "Tonemapping peak:", + "LabelTonemappingPeakHelp": "Override signal/nominal/reference peak with this value. Useful when the embedded peak information in display metadata is not reliable or when tone mapping from a lower range to a higher range. The recommended and default values are 0.", + "LabelTonemappingParam": "Tonemapping param:", + "LabelTonemappingParamHelp": "Tune the tone mapping algorithm. The recommended and default values are NaN. Generally leave it blank.", + "StopPlayback": "Stop playback", + "ClearQueue": "Clear queue", + "LabelSubtitleVerticalPosition": "Vertical position:", + "SubtitleVerticalPositionHelp": "Line number where text appears. Positive numbers indicate top down. Negative numbers indicate bottom up.", + "Preview": "Preview", + "LabelMaxMuxingQueueSize": "Max muxing queue size:", + "LabelMaxMuxingQueueSizeHelp": "Maximum number of packets that can be buffered while waiting for all streams to initialize. Try to increase it if you still encounter \"Too many packets buffered for output stream\" error in ffmpeg logs. The recommended value is 2048.", + + "LabelCreateHttpPortMap": "Enable automatic port mapping for http traffic as well as https.", + "LabelCreateHttpPortMapHelp": "Permit automatic port mapping to create a rule for http traffic in addition to https traffic.", + "HeaderAutoDiscovery": "Network Discovery", + "LabelAutomaticDiscovery": "Enable Auto Discovery:", + "LabelAutomaticDiscoveryHelp": "Enable applications to detect Jellyfin automatically on udp port 7359.", + "LabelAutoDiscoveryTracing": "Enable Auto Discovery tracing.", + "LabelAutoDiscoveryTracingHelp": "When enabled, packets received on the auto discovery port will be logged.", + "HeaderPortRanges": "Firewall and Proxy Settings", + "LabelUDPPortRange": "UDP Communication Range:", + "LabelUDPPortRangeHelp": "Restrict Jellyfin to use this port range when making UDP connections. (Default is 1024 - 645535).
Note: Certain function require fixed ports that may be outside of this range.", + "LabelHDHomerunPortRange": "HD Homerun Range:", + "LabelHDHomerunPortRangeHelp": "Restricts the HD Homerun UDP port range to this value. (Default is 1024 - 645535).", + "LabelPublishedServerUri": "Published Server URIs:", + "LabelPublishedServerUriHelp": "Override the URI used by Jellyfin, based on the interface, or client IP address.", + "HeaderDebugging": "Debugging and Tracing", + "LabelEnableSSDPTracing": "Enable SSDP Tracing:", + "LabelEnableSSDPTracingHelp": "Enable details SSDP network tracing to be logged.
WARNING: This will cause serious performance degradation.", + "LabelSSDPTracingFilter": "SSDP Filter:", + "LabelSSDPTracingFilterHelp": "Optional IP address upon which to filter the logged SSDP traffic.", + "LabelEnableIP6Help": "Enables IPv6 functionality.", + + "LabelEnableIP6": "Enable IPv6:", + "LabelEnableIP4Help": "Enables IPv4 functionality.", + "LabelEnableIP4": "Enable IPv4:", + "HeaderNetworking": "IP Protocols" +} } From 020b955cfd498eb4188a68b1aa3d4646911b744e Mon Sep 17 00:00:00 2001 From: Greenback Date: Sat, 10 Oct 2020 15:37:39 +0100 Subject: [PATCH 021/202] Updated --- src/controllers/dashboard/networking.html | 76 + src/controllers/dashboard/networking.js | 43 +- src/strings/en-gb.json | 26 +- src/strings/en-us.json | 2870 +++++++++++---------- 4 files changed, 1586 insertions(+), 1429 deletions(-) diff --git a/src/controllers/dashboard/networking.html b/src/controllers/dashboard/networking.html index 9fb08aa661..60b2ffee37 100644 --- a/src/controllers/dashboard/networking.html +++ b/src/controllers/dashboard/networking.html @@ -105,6 +105,13 @@
${LabelEnableAutomaticPortMapHelp}
+
+ +
${LabelCreateHttpPortMapHelp}
+
${LabelPublicHttpPortHelp}
@@ -114,6 +121,75 @@
${LabelPublicHttpsPortHelp}
+ +
+

${HeaderNetworking}

+
+ +
${LabelEnableIP4Help}
+
+
+ +
${LabelEnableIP6Help}
+
+
+ + +
+

${HeaderAutoDiscovery}

+
+ +
${LabelAutomaticDiscoveryHelp}
+
+
+ +
+

${HeaderPortRanges}

+ +
+ +
${LabelPublishedServerUriHelp}
+
+
+ +
${LabelUDPPortRangeHelp}
+
+
+ +
${LabelHDHomerunPortRangeHelp}
+
+
+ +
+

${HeaderDebugging}

+
+ +
${LabelEnableSSDPTracingHelp}
+
+
+ +
${LabelSSDPTracingFilterHelp}
+
+
+ +
${LabelAutoDiscoveryTracingHelp}
+
+
'; } @@ -1461,7 +1462,7 @@ import 'programStyles'; const likes = userData.Likes == null ? '' : userData.Likes; /* eslint-disable-next-line @babel/no-unused-expressions */ - import('emby-ratingbutton'); + import('../../elements/emby-ratingbutton/emby-ratingbutton'); html += ''; } diff --git a/src/components/cardbuilder/chaptercardbuilder.js b/src/components/cardbuilder/chaptercardbuilder.js index 35ae2b0cdd..2ebdcbe820 100644 --- a/src/components/cardbuilder/chaptercardbuilder.js +++ b/src/components/cardbuilder/chaptercardbuilder.js @@ -5,10 +5,11 @@ * @module components/cardBuilder/chaptercardbuilder */ -import datetime from 'datetime'; -import imageLoader from 'imageLoader'; -import layoutManager from 'layoutManager'; -import browser from 'browser'; +import datetime from '../../scripts/datetime'; +import imageLoader from '../images/imageLoader'; +import connectionManager from 'jellyfin-apiclient'; +import layoutManager from '../layoutManager'; +import browser from '../../scripts/browser'; const enableFocusTransform = !browser.slow && !browser.edge; diff --git a/src/components/cardbuilder/peoplecardbuilder.js b/src/components/cardbuilder/peoplecardbuilder.js index 5fc9e8ade5..de2dfb64a2 100644 --- a/src/components/cardbuilder/peoplecardbuilder.js +++ b/src/components/cardbuilder/peoplecardbuilder.js @@ -5,7 +5,7 @@ * @module components/cardBuilder/peoplecardbuilder */ -import cardBuilder from 'cardBuilder'; +import cardBuilder from '../cardbuilder/cardBuilder'; export function buildPeopleCards(items, options) { options = Object.assign(options || {}, { diff --git a/src/components/channelMapper/channelMapper.js b/src/components/channelMapper/channelMapper.js index 294f9e223a..b3a3dc41bc 100644 --- a/src/components/channelMapper/channelMapper.js +++ b/src/components/channelMapper/channelMapper.js @@ -1,14 +1,15 @@ -import dom from 'dom'; -import dialogHelper from 'dialogHelper'; -import loading from 'loading'; -import globalize from 'globalize'; -import actionsheet from 'actionsheet'; -import 'emby-input'; -import 'paper-icon-button-light'; -import 'emby-button'; -import 'listViewStyle'; -import 'material-icons'; -import 'formDialogStyle'; +import dom from '../../scripts/dom'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import loading from '../loading/loading'; +import connectionManager from 'jellyfin-apiclient'; +import globalize from '../../scripts/globalize'; +import actionsheet from '../actionSheet/actionSheet'; +import '../../elements/emby-input/emby-input'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-button/emby-button'; +import '../listview/listview.css'; +import 'material-design-icons-iconfont'; +import '../formdialog.css'; export default class channelMapper { constructor(options) { diff --git a/src/components/collectionEditor/collectionEditor.js b/src/components/collectionEditor/collectionEditor.js index 2d0d025929..e36abd7e0f 100644 --- a/src/components/collectionEditor/collectionEditor.js +++ b/src/components/collectionEditor/collectionEditor.js @@ -1,17 +1,18 @@ -import dom from 'dom'; -import dialogHelper from 'dialogHelper'; -import loading from 'loading'; -import layoutManager from 'layoutManager'; -import appRouter from 'appRouter'; -import globalize from 'globalize'; -import 'emby-checkbox'; -import 'emby-input'; -import 'paper-icon-button-light'; -import 'emby-select'; -import 'material-icons'; -import 'css!./../formdialog'; -import 'emby-button'; -import 'flexStyles'; +import dom from '../../scripts/dom'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import loading from '../loading/loading'; +import layoutManager from '../layoutManager'; +import connectionManager from 'jellyfin-apiclient'; +import appRouter from '../appRouter'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-input/emby-input'; +import '../../elements/emby-select/emby-select'; +import 'material-design-icons-iconfont'; +import '../formdialog.css'; +import '../../assets/css/flexstyles.css'; /* eslint-disable indent */ @@ -80,7 +81,7 @@ import 'flexStyles'; dlg.submitted = true; dialogHelper.close(dlg); - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('MessageItemsAdded')); }); }); @@ -199,7 +200,7 @@ import 'flexStyles'; } function centerFocus(elem, horiz, on) { - import('scrollHelper').then((scrollHelper) => { + import('../../scripts/scrollHelper').then((scrollHelper) => { const fn = on ? 'on' : 'off'; scrollHelper.centerFocus[fn](elem, horiz); }); diff --git a/src/components/confirm/confirm.js b/src/components/confirm/confirm.js index eca612ccb8..4f3b09c2d1 100644 --- a/src/components/confirm/confirm.js +++ b/src/components/confirm/confirm.js @@ -1,6 +1,6 @@ -import browser from 'browser'; -import dialog from 'dialog'; -import globalize from 'globalize'; +import browser from '../../scripts/browser'; +import dialog from '../dialog/dialog'; +import globalize from '../../scripts/globalize'; /* eslint-disable indent */ export default (() => { diff --git a/src/components/dialog/dialog.js b/src/components/dialog/dialog.js index 1b13900d85..cb765242cb 100644 --- a/src/components/dialog/dialog.js +++ b/src/components/dialog/dialog.js @@ -1,14 +1,14 @@ -import dialogHelper from 'dialogHelper'; -import dom from 'dom'; -import layoutManager from 'layoutManager'; -import scrollHelper from 'scrollHelper'; -import globalize from 'globalize'; -import 'material-icons'; -import 'emby-button'; -import 'paper-icon-button-light'; -import 'emby-input'; -import 'formDialogStyle'; -import 'flexStyles'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import dom from '../../scripts/dom'; +import layoutManager from '../layoutManager'; +import scrollHelper from '../../scripts/scrollHelper'; +import globalize from '../../scripts/globalize'; +import 'material-design-icons-iconfont'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-input/emby-input'; +import '../formdialog.css'; +import '../../assets/css/flexstyles.css'; /* eslint-disable indent */ @@ -80,7 +80,8 @@ import 'flexStyles'; buttonClass += ' formDialogFooterItem-vertical formDialogFooterItem-nomarginbottom'; } - html += ``; + html += ``; if (item.description) { html += `
${item.description}
`; @@ -128,7 +129,7 @@ import 'flexStyles'; options = text; } - const { default: template } = await import('text!./dialog.template.html'); + const { default: template } = await import('./dialog.template.html'); return new Promise((resolve, reject) => { showDialog(options, template).then(resolve, reject); }); diff --git a/src/components/dialogHelper/dialogHelper.js b/src/components/dialogHelper/dialogHelper.js index eb46d98b12..4eee793a39 100644 --- a/src/components/dialogHelper/dialogHelper.js +++ b/src/components/dialogHelper/dialogHelper.js @@ -1,11 +1,11 @@ -import appRouter from 'appRouter'; -import focusManager from 'focusManager'; -import browser from 'browser'; -import layoutManager from 'layoutManager'; -import inputManager from 'inputManager'; -import dom from 'dom'; -import 'css!./dialoghelper.css'; -import 'scrollStyles'; +import appRouter from '../appRouter'; +import focusManager from '../focusManager'; +import browser from '../../scripts/browser'; +import layoutManager from '../layoutManager'; +import inputManager from '../../scripts/inputManager'; +import dom from '../../scripts/dom'; +import './dialoghelper.css'; +import '../../assets/css/scrollstyles.css'; /* eslint-disable indent */ @@ -354,7 +354,7 @@ import 'scrollStyles'; } function centerFocus(elem, horiz, on) { - import('scrollHelper').then((scrollHelper) => { + import('../../scripts/scrollHelper').then((scrollHelper) => { const fn = on ? 'on' : 'off'; scrollHelper.centerFocus[fn](elem, horiz); }); diff --git a/src/components/directorybrowser/directorybrowser.js b/src/components/directorybrowser/directorybrowser.js index 3dd3302b28..939fedbf0b 100644 --- a/src/components/directorybrowser/directorybrowser.js +++ b/src/components/directorybrowser/directorybrowser.js @@ -1,13 +1,13 @@ -import loading from 'loading'; -import dialogHelper from 'dialogHelper'; -import dom from 'dom'; -import globalize from 'globalize'; -import 'listViewStyle'; -import 'emby-input'; -import 'paper-icon-button-light'; -import 'css!./directorybrowser'; -import 'formDialogStyle'; -import 'emby-button'; +import loading from '../loading/loading'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import dom from '../../scripts/dom'; +import globalize from '../../scripts/globalize'; +import '../listview/listview.css'; +import '../../elements/emby-input/emby-input'; +import '../../elements/emby-button/paper-icon-button-light'; +import './directorybrowser.css'; +import '../formdialog.css'; +import '../../elements/emby-button/emby-button'; /* eslint-disable indent */ @@ -157,7 +157,7 @@ import 'emby-button'; } function alertTextWithOptions(options) { - import('alert').then(({default: alert}) => { + import('../alert').then((alert) => { alert(options); }); } diff --git a/src/components/displaySettings/displaySettings.js b/src/components/displaySettings/displaySettings.js index efaab16b3f..d6e4bee2fe 100644 --- a/src/components/displaySettings/displaySettings.js +++ b/src/components/displaySettings/displaySettings.js @@ -1,16 +1,17 @@ -import browser from 'browser'; -import layoutManager from 'layoutManager'; -import pluginManager from 'pluginManager'; -import appHost from 'apphost'; -import focusManager from 'focusManager'; -import datetime from 'datetime'; -import globalize from 'globalize'; -import loading from 'loading'; -import skinManager from 'skinManager'; -import events from 'events'; -import 'emby-select'; -import 'emby-checkbox'; -import 'emby-button'; +import browser from '../../scripts/browser'; +import layoutManager from '../layoutManager'; +import pluginManager from '../pluginManager'; +import appHost from '../apphost'; +import focusManager from '../focusManager'; +import datetime from '../../scripts/datetime'; +import globalize from '../../scripts/globalize'; +import loading from '../loading/loading'; +import connectionManager from 'jellyfin-apiclient'; +import skinManager from '../../scripts/themeManager'; +import events from 'jellyfin-apiclient'; +import '../../elements/emby-select/emby-select'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-button/emby-button'; /* eslint-disable indent */ @@ -168,7 +169,7 @@ import 'emby-button'; saveUser(context, user, userSettings, apiClient).then(() => { loading.hide(); if (enableSaveConfirmation) { - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('SettingsSaved')); }); } @@ -198,7 +199,7 @@ import 'emby-button'; } async function embed(options, self) { - const { default: template } = await import('text!./displaySettings.template.html'); + const { default: template } = await import('./displaySettings.template.html'); options.element.innerHTML = globalize.translateHtml(template, 'core'); options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self)); if (options.enableSaveButton) { diff --git a/src/components/favoriteitems.js b/src/components/favoriteitems.js index 86cd050216..7b56967fdd 100644 --- a/src/components/favoriteitems.js +++ b/src/components/favoriteitems.js @@ -1,12 +1,12 @@ -import loading from 'loading'; -import cardBuilder from 'cardBuilder'; -import dom from 'dom'; -import appHost from 'apphost'; -import imageLoader from 'imageLoader'; -import globalize from 'globalize'; -import layoutManager from 'layoutManager'; -import 'scrollStyles'; -import 'emby-itemscontainer'; +import loading from './loading/loading'; +import cardBuilder from './cardbuilder/cardBuilder'; +import dom from '../scripts/dom'; +import appHost from './apphost'; +import imageLoader from './images/imageLoader'; +import globalize from '../scripts/globalize'; +import layoutManager from './layoutManager'; +import '../assets/css/scrollstyles.css'; +import '../elements/emby-itemscontainer/emby-itemscontainer'; /* eslint-disable indent */ diff --git a/src/components/filterdialog/filterdialog.js b/src/components/filterdialog/filterdialog.js index d11edb40a2..9c5ad5f71d 100644 --- a/src/components/filterdialog/filterdialog.js +++ b/src/components/filterdialog/filterdialog.js @@ -1,10 +1,11 @@ -import dom from 'dom'; -import dialogHelper from 'dialogHelper'; -import globalize from 'globalize'; -import events from 'events'; -import 'emby-checkbox'; -import 'emby-collapse'; -import 'css!./style.css'; +import dom from '../../scripts/dom'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import globalize from '../../scripts/globalize'; +import connectionManager from 'jellyfin-apiclient'; +import events from 'jellyfin-apiclient'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-collapse/emby-collapse'; +import './style.css'; /* eslint-disable indent */ function renderOptions(context, selector, cssClass, items, isCheckedFn) { @@ -401,7 +402,7 @@ import 'css!./style.css'; } show() { - return import('text!./filterdialog.template.html').then(({default: template}) => { + return import('./filterdialog.template.html').then(({default: template}) => { return new Promise((resolve) => { const dlg = dialogHelper.createDialog({ removeOnClose: true, diff --git a/src/components/filtermenu/filtermenu.js b/src/components/filtermenu/filtermenu.js index 7cef08303d..46c3fc87b7 100644 --- a/src/components/filtermenu/filtermenu.js +++ b/src/components/filtermenu/filtermenu.js @@ -1,18 +1,19 @@ -import dom from 'dom'; -import focusManager from 'focusManager'; -import dialogHelper from 'dialogHelper'; -import inputManager from 'inputManager'; -import layoutManager from 'layoutManager'; -import globalize from 'globalize'; -import * as userSettings from 'userSettings'; -import 'emby-checkbox'; -import 'emby-input'; -import 'paper-icon-button-light'; -import 'emby-select'; -import 'material-icons'; -import 'css!./../formdialog'; -import 'emby-button'; -import 'flexStyles'; +import dom from '../../scripts/dom'; +import focusManager from '../focusManager'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import inputManager from '../../scripts/inputManager'; +import layoutManager from '../layoutManager'; +import connectionManager from 'jellyfin-apiclient'; +import globalize from '../../scripts/globalize'; +import * as userSettings from '../../scripts/settings/userSettings'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-input/emby-input'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-select/emby-select'; +import 'material-design-icons-iconfont'; +import '../formdialog.css'; +import '../../assets/css/flexstyles.css'; function onSubmit(e) { e.preventDefault(); @@ -80,7 +81,7 @@ function moveCheckboxFocus(elem, offset) { } } function centerFocus(elem, horiz, on) { - import('scrollHelper').then(({ default: scrollHelper }) => { + import('../../scripts/scrollHelper').then((scrollHelper) => { const fn = on ? 'on' : 'off'; scrollHelper.centerFocus[fn](elem, horiz); }); @@ -209,7 +210,7 @@ function loadDynamicFilters(context, options) { class FilterMenu { show(options) { return new Promise( (resolve, reject) => { - import('text!./filtermenu.template.html').then(({ default: template }) => { + import('./filtermenu.template.html').then(({ default: template }) => { const dialogOptions = { removeOnClose: true, scrollY: false diff --git a/src/components/focusManager.js b/src/components/focusManager.js index d45984bf58..b0fc188516 100644 --- a/src/components/focusManager.js +++ b/src/components/focusManager.js @@ -1,7 +1,7 @@ /* eslint-disable indent */ -import dom from 'dom'; -import scrollManager from 'scrollManager'; +import dom from '../scripts/dom'; +import scrollManager from './scrollManager'; const scopes = []; function pushScope(elem) { diff --git a/src/components/groupedcards.js b/src/components/groupedcards.js index 947b3b8569..c2714eba8d 100644 --- a/src/components/groupedcards.js +++ b/src/components/groupedcards.js @@ -1,7 +1,8 @@ /* eslint-disable indent */ -import dom from 'dom'; -import appRouter from 'appRouter'; +import dom from '../scripts/dom'; +import appRouter from './appRouter'; +import connectionManager from 'jellyfin-apiclient'; function onGroupedCardClick(e, card) { const itemId = card.getAttribute('data-id'); diff --git a/src/components/guide/guide-settings.js b/src/components/guide/guide-settings.js index 35f0d3e06e..8132ac3bb3 100644 --- a/src/components/guide/guide-settings.js +++ b/src/components/guide/guide-settings.js @@ -1,12 +1,12 @@ -import dialogHelper from 'dialogHelper'; -import globalize from 'globalize'; -import * as userSettings from 'userSettings'; -import layoutManager from 'layoutManager'; -import scrollHelper from 'scrollHelper'; -import 'emby-checkbox'; -import 'emby-radio'; -import 'css!./../formdialog'; -import 'material-icons'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import globalize from '../../scripts/globalize'; +import * as userSettings from '../../scripts/settings/userSettings'; +import layoutManager from '../layoutManager'; +import scrollHelper from '../../scripts/scrollHelper'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-radio/emby-radio'; +import '../formdialog.css'; +import 'material-design-icons-iconfont'; function saveCategories(context, options) { const categories = []; @@ -88,7 +88,7 @@ function showEditor(options) { return new Promise(function (resolve, reject) { let settingsChanged = false; - import('text!./guide-settings.template.html').then(({ default: template }) => { + import('./guide-settings.template.html').then(({ default: template }) => { const dialogOptions = { removeOnClose: true, scrollY: false diff --git a/src/components/guide/guide.js b/src/components/guide/guide.js index a5ed55e67c..92a528f000 100644 --- a/src/components/guide/guide.js +++ b/src/components/guide/guide.js @@ -1,32 +1,33 @@ -import inputManager from 'inputManager'; -import browser from 'browser'; -import globalize from 'globalize'; -import scrollHelper from 'scrollHelper'; -import serverNotifications from 'serverNotifications'; -import loading from 'loading'; -import datetime from 'datetime'; -import focusManager from 'focusManager'; -import playbackManager from 'playbackManager'; -import * as userSettings from 'userSettings'; -import imageLoader from 'imageLoader'; -import events from 'events'; -import layoutManager from 'layoutManager'; -import itemShortcuts from 'itemShortcuts'; -import dom from 'dom'; -import 'css!./guide.css'; -import 'programStyles'; -import 'material-icons'; -import 'scrollStyles'; -import 'emby-programcell'; -import 'emby-button'; -import 'paper-icon-button-light'; -import 'emby-tabs'; -import 'emby-scroller'; -import 'flexStyles'; -import 'webcomponents'; +import inputManager from '../../scripts/inputManager'; +import browser from '../../scripts/browser'; +import globalize from '../../scripts/globalize'; +import connectionManager from 'jellyfin-apiclient'; +import scrollHelper from '../../scripts/scrollHelper'; +import serverNotifications from '../../scripts/serverNotifications'; +import loading from '../loading/loading'; +import datetime from '../../scripts/datetime'; +import focusManager from '../focusManager'; +import playbackManager from '../playback/playbackmanager'; +import * as userSettings from '../../scripts/settings/userSettings'; +import imageLoader from '../images/imageLoader'; +import events from 'jellyfin-apiclient'; +import layoutManager from '../layoutManager'; +import itemShortcuts from '../shortcuts'; +import dom from '../../scripts/dom'; +import './guide.css'; +import './programs.css'; +import 'material-design-icons-iconfont'; +import '../../assets/css/scrollstyles.css'; +import '../../elements/emby-programcell/emby-programcell'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-tabs/emby-tabs'; +import '../../elements/emby-scroller/emby-scroller'; +import '../../assets/css/flexstyles.css'; +import 'webcomponents.js'; function showViewSettings(instance) { - import('guide-settings-dialog').then(({default: guideSettingsDialog}) => { + import('./guide-settings').then((guideSettingsDialog) => { guideSettingsDialog.show(instance.categoryOptions).then(function () { instance.refresh(); }); @@ -1091,7 +1092,7 @@ function Guide(options) { } } - import('text!./tvguide.template.html').then(({default: template}) => { + import('./tvguide.template.html').then(({default: template}) => { const context = options.element; context.classList.add('tvguide'); diff --git a/src/components/homeScreenSettings/homeScreenSettings.js b/src/components/homeScreenSettings/homeScreenSettings.js index 5138935408..361a91a9e3 100644 --- a/src/components/homeScreenSettings/homeScreenSettings.js +++ b/src/components/homeScreenSettings/homeScreenSettings.js @@ -1,13 +1,15 @@ -import layoutManager from 'layoutManager'; -import focusManager from 'focusManager'; -import globalize from 'globalize'; -import loading from 'loading'; -import homeSections from 'homeSections'; -import dom from 'dom'; -import events from 'events'; -import 'listViewStyle'; -import 'emby-select'; -import 'emby-checkbox'; + +import layoutManager from '../layoutManager'; +import focusManager from '../focusManager'; +import globalize from '../../scripts/globalize'; +import loading from '../loading/loading'; +import connectionManager from 'jellyfin-apiclient'; +import homeSections from '../homesections/homesections'; +import dom from '../../scripts/dom'; +import events from 'jellyfin-apiclient'; +import '../listview/listview.css'; +import '../../elements/emby-select/emby-select'; +import '../../elements/emby-checkbox/emby-checkbox'; /* eslint-disable indent */ @@ -369,7 +371,7 @@ import 'emby-checkbox'; saveUser(context, user, userSettings, apiClient).then(() => { loading.hide(); if (enableSaveConfirmation) { - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('SettingsSaved')); }); } @@ -417,7 +419,7 @@ import 'emby-checkbox'; } function embed(options, self) { - return import('text!./homeScreenSettings.template.html').then(({default: template}) => { + return import('./homeScreenSettings.template.html').then(({default: template}) => { for (let i = 1; i <= numConfigurableSections; i++) { template = template.replace(`{section${i}label}`, globalize.translate('LabelHomeScreenSectionValue', i)); } diff --git a/src/components/homesections/homesections.js b/src/components/homesections/homesections.js index 758773689b..60c5fc0ac4 100644 --- a/src/components/homesections/homesections.js +++ b/src/components/homesections/homesections.js @@ -1,15 +1,16 @@ -import cardBuilder from 'cardBuilder'; -import dom from 'dom'; -import layoutManager from 'layoutManager'; -import imageLoader from 'imageLoader'; -import globalize from 'globalize'; -import appRouter from 'appRouter'; -import imageHelper from 'scripts/imagehelper'; -import 'paper-icon-button-light'; -import 'emby-itemscontainer'; -import 'emby-scroller'; -import 'emby-button'; -import 'css!./homesections'; +import connectionManager from 'jellyfin-apiclient'; +import cardBuilder from '../cardbuilder/cardBuilder'; +import dom from '../../scripts/dom'; +import layoutManager from '../layoutManager'; +import imageLoader from '../images/imageLoader'; +import globalize from '../../scripts/globalize'; +import appRouter from '../appRouter'; +import imageHelper from '../../scripts/imagehelper'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; +import '../../elements/emby-scroller/emby-scroller'; +import '../../elements/emby-button/emby-button'; +import './homesections'; /* eslint-disable indent */ diff --git a/src/components/htmlMediaHelper.js b/src/components/htmlMediaHelper.js index be506b449d..1fab10ef2b 100644 --- a/src/components/htmlMediaHelper.js +++ b/src/components/htmlMediaHelper.js @@ -1,8 +1,9 @@ + /* eslint-disable indent */ -import appSettings from 'appSettings' ; -import browser from 'browser'; -import events from 'events'; +import appSettings from '../scripts/settings/appSettings' ; +import browser from '../scripts/browser'; +import events from 'jellyfin-apiclient'; export function getSavedVolume() { return appSettings.get('volume') || 1; diff --git a/src/components/imageDownloader/imageDownloader.js b/src/components/imageDownloader/imageDownloader.js index 1ec459ff83..5abdd588fa 100644 --- a/src/components/imageDownloader/imageDownloader.js +++ b/src/components/imageDownloader/imageDownloader.js @@ -1,17 +1,18 @@ -import dom from 'dom'; -import loading from 'loading'; -import appHost from 'apphost'; -import dialogHelper from 'dialogHelper'; -import imageLoader from 'imageLoader'; -import browser from 'browser'; -import layoutManager from 'layoutManager'; -import scrollHelper from 'scrollHelper'; -import globalize from 'globalize'; -import 'emby-checkbox'; -import 'paper-icon-button-light'; -import 'emby-button'; -import 'formDialogStyle'; -import 'cardStyle'; +import dom from '../../scripts/dom'; +import loading from '../loading/loading'; +import appHost from '../apphost'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import connectionManager from 'jellyfin-apiclient'; +import imageLoader from '../images/imageLoader'; +import browser from '../../scripts/browser'; +import layoutManager from '../layoutManager'; +import scrollHelper from '../../scripts/scrollHelper'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-button/emby-button'; +import '../formdialog.css'; +import '../cardbuilder/card.css'; /* eslint-disable indent */ @@ -315,7 +316,7 @@ import 'cardStyle'; function showEditor(itemId, serverId, itemType) { loading.show(); - import('text!./imageDownloader.template.html').then(({default: template}) => { + import('./imageDownloader.template.html').then(({default: template}) => { const apiClient = window.connectionManager.getApiClient(serverId); currentItemId = itemId; diff --git a/src/components/imageOptionsEditor/imageOptionsEditor.js b/src/components/imageOptionsEditor/imageOptionsEditor.js index d112dd65cc..a220a65c5d 100644 --- a/src/components/imageOptionsEditor/imageOptionsEditor.js +++ b/src/components/imageOptionsEditor/imageOptionsEditor.js @@ -5,12 +5,12 @@ * @module components/imageOptionsEditor/imageOptionsEditor */ -import globalize from 'globalize'; -import dom from 'dom'; -import dialogHelper from 'dialogHelper'; -import 'emby-checkbox'; -import 'emby-select'; -import 'emby-input'; +import globalize from '../../scripts/globalize'; +import dom from '../../scripts/dom'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-select/emby-select'; +import '../../elements/emby-input/emby-input'; function getDefaultImageConfig(itemType, type) { return { diff --git a/src/components/imageUploader/imageUploader.js b/src/components/imageUploader/imageUploader.js index e89cbda2ae..2c32accca3 100644 --- a/src/components/imageUploader/imageUploader.js +++ b/src/components/imageUploader/imageUploader.js @@ -5,16 +5,17 @@ * @module components/imageUploader/imageUploader */ -import dialogHelper from 'dialogHelper'; -import dom from 'dom'; -import loading from 'loading'; -import scrollHelper from 'scrollHelper'; -import layoutManager from 'layoutManager'; -import globalize from 'globalize'; -import 'emby-button'; -import 'emby-select'; -import 'formDialogStyle'; -import 'css!./style'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import connectionManager from 'jellyfin-apiclient'; +import dom from '../../scripts/dom'; +import loading from '../loading/loading'; +import scrollHelper from '../../scripts/scrollHelper'; +import layoutManager from '../layoutManager'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-select/emby-select'; +import '../formdialog.css'; +import './style.css'; let currentItemId; let currentServerId; @@ -26,14 +27,14 @@ import 'css!./style'; switch (evt.target.error.code) { case evt.target.error.NOT_FOUND_ERR: - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('MessageFileReadError')); }); break; case evt.target.error.ABORT_ERR: break; // noop default: - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('MessageFileReadError')); }); break; @@ -87,7 +88,7 @@ import 'css!./style'; } if (!file.type.startsWith('image/')) { - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('MessageImageFileTypeAllowed')); }); e.preventDefault(); @@ -100,7 +101,7 @@ import 'css!./style'; const imageType = dlg.querySelector('#selectImageType').value; if (imageType === 'None') { - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('MessageImageTypeNotSelected')); }); e.preventDefault(); @@ -134,7 +135,7 @@ import 'css!./style'; function showEditor(options, resolve) { options = options || {}; - return import('text!./imageUploader.template.html').then(({default: template}) => { + return import('./imageUploader.template.html').then(({default: template}) => { currentItemId = options.itemId; currentServerId = options.serverId; diff --git a/src/components/imageeditor/imageeditor.js b/src/components/imageeditor/imageeditor.js index e5b59cfb22..09edc072fe 100644 --- a/src/components/imageeditor/imageeditor.js +++ b/src/components/imageeditor/imageeditor.js @@ -1,18 +1,19 @@ -import dialogHelper from 'dialogHelper'; -import loading from 'loading'; -import dom from 'dom'; -import layoutManager from 'layoutManager'; -import focusManager from 'focusManager'; -import globalize from 'globalize'; -import scrollHelper from 'scrollHelper'; -import imageLoader from 'imageLoader'; -import browser from 'browser'; -import appHost from 'apphost'; -import 'cardStyle'; -import 'formDialogStyle'; -import 'emby-button'; -import 'paper-icon-button-light'; -import 'css!./imageeditor'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import connectionManager from 'jellyfin-apiclient'; +import loading from '../loading/loading'; +import dom from '../../scripts/dom'; +import layoutManager from '../layoutManager'; +import focusManager from '../focusManager'; +import globalize from '../../scripts/globalize'; +import scrollHelper from '../../scripts/scrollHelper'; +import imageLoader from '../images/imageLoader'; +import browser from '../../scripts/browser'; +import appHost from '../apphost'; +import '../cardbuilder/card.css'; +import '../formdialog.css'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-button/paper-icon-button-light'; +import './imageeditor.css'; /* eslint-disable indent */ @@ -199,7 +200,7 @@ import 'css!./imageeditor'; return; } - import('confirm').then(({default: confirm}) => { + import('../confirm/confirm').then(({default: confirm}) => { confirm({ text: globalize.translate('ConfirmDeleteImage'), @@ -215,7 +216,7 @@ import 'css!./imageeditor'; hasChanges = true; reload(context, null, focusContext); }, function () { - import('alert').then(({default: alert}) => { + import('../alert').then((alert) => { alert(globalize.translate('ErrorDefault')); }); }); @@ -281,7 +282,7 @@ import 'css!./imageeditor'; } function showImageDownloader(page, imageType) { - import('imageDownloader').then(({default: ImageDownloader}) => { + import('../imageDownloader/imageDownloader').then((ImageDownloader) => { ImageDownloader.show(currentItem.Id, currentItem.ServerId, currentItem.Type, imageType).then(function () { hasChanges = true; reload(page); @@ -299,7 +300,7 @@ import 'css!./imageeditor'; const providerCount = parseInt(imageCard.getAttribute('data-providers')); const numImages = parseInt(imageCard.getAttribute('data-numimages')); - import('actionsheet').then(({default: actionSheet}) => { + import('../actionSheet/actionSheet').then(({default: actionSheet}) => { const commands = []; commands.push({ @@ -370,7 +371,7 @@ import 'css!./imageeditor'; addListeners(context, 'btnOpenUploadMenu', 'click', function () { const imageType = this.getAttribute('data-imagetype'); - import('imageUploader').then(({default: imageUploader}) => { + import('../imageUploader/imageUploader').then(({default: imageUploader}) => { imageUploader.show({ theme: options.theme, @@ -422,7 +423,7 @@ import 'css!./imageeditor'; loading.show(); - import('text!./imageeditor.template.html').then(({default: template}) => { + import('./imageeditor.template.html').then(({default: template}) => { const apiClient = window.connectionManager.getApiClient(serverId); apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) { const dialogOptions = { diff --git a/src/components/images/imageLoader.js b/src/components/images/imageLoader.js index 9dc708098d..f4a141bc90 100644 --- a/src/components/images/imageLoader.js +++ b/src/components/images/imageLoader.js @@ -1,7 +1,7 @@ -import * as lazyLoader from 'lazyLoader'; -import * as userSettings from 'userSettings'; +import * as lazyLoader from '../lazyLoader/lazyLoaderIntersectionObserver'; +import * as userSettings from '../../scripts/settings/userSettings'; import * as blurhash from 'blurhash'; -import 'css!./style'; +import './style.css'; /* eslint-disable indent */ export function lazyImage(elem, source = elem.getAttribute('data-src')) { diff --git a/src/components/indicators/indicators.js b/src/components/indicators/indicators.js index bbd672ef72..5f8a8691d1 100644 --- a/src/components/indicators/indicators.js +++ b/src/components/indicators/indicators.js @@ -1,8 +1,8 @@ -import datetime from 'datetime'; -import itemHelper from 'itemHelper'; -import 'emby-progressbar'; -import 'css!./indicators.css'; -import 'material-icons'; +import datetime from '../../scripts/datetime'; +import itemHelper from '../itemHelper'; +import '../../elements/emby-progressbar/emby-progressbar'; +import './indicators.css'; +import 'material-design-icons-iconfont'; export function enableProgressIndicator(item) { if (item.MediaType === 'Video' && item.Type !== 'TvChannel') { diff --git a/src/components/itemContextMenu.js b/src/components/itemContextMenu.js index f36f623d9f..ff58a901f4 100644 --- a/src/components/itemContextMenu.js +++ b/src/components/itemContextMenu.js @@ -1,10 +1,11 @@ -import appHost from 'apphost'; -import globalize from 'globalize'; -import itemHelper from 'itemHelper'; -import appRouter from 'appRouter'; -import playbackManager from 'playbackManager'; -import browser from 'browser'; -import actionsheet from 'actionsheet'; +import connectionManager from 'jellyfin-apiclient'; +import browser from '../scripts/browser'; +import globalize from '../scripts/globalize'; +import actionsheet from './actionSheet/actionSheet'; +import appHost from './apphost'; +import appRouter from './appRouter'; +import itemHelper from './itemHelper'; +import playbackManager from './playback/playbackmanager'; /* eslint-disable indent */ export function getCommands(options) { @@ -334,7 +335,7 @@ import actionsheet from 'actionsheet'; return new Promise(function (resolve, reject) { switch (id) { case 'addtocollection': - import('collectionEditor').then(({default: collectionEditor}) => { + import('./collectionEditor/collectionEditor').then((collectionEditor) => { new collectionEditor({ items: [itemId], serverId: serverId @@ -342,7 +343,7 @@ import actionsheet from 'actionsheet'; }); break; case 'addtoplaylist': - import('playlistEditor').then(({default: playlistEditor}) => { + import('./playlisteditor/playlisteditor').then((playlistEditor) => { new playlistEditor({ items: [itemId], serverId: serverId @@ -350,7 +351,7 @@ import actionsheet from 'actionsheet'; }); break; case 'download': - import('fileDownloader').then((fileDownloader) => { + import('../scripts/fileDownloader').then((fileDownloader) => { const downloadHref = apiClient.getItemDownloadUrl(itemId); fileDownloader.download([{ url: downloadHref, @@ -372,7 +373,7 @@ import actionsheet from 'actionsheet'; textArea.select(); if (document.execCommand('copy')) { - import('toast').then(({default: toast}) => { + import('./toast/toast').then((toast) => { toast(globalize.translate('CopyStreamURLSuccess')); }); } else { @@ -387,7 +388,7 @@ import actionsheet from 'actionsheet'; } else { /* eslint-disable-next-line compat/compat */ navigator.clipboard.writeText(downloadHref).then(function () { - import('toast').then(({default: toast}) => { + import('./toast/toast').then((toast) => { toast(globalize.translate('CopyStreamURLSuccess')); }); }).catch(function () { @@ -398,7 +399,7 @@ import actionsheet from 'actionsheet'; break; } case 'editsubtitles': - import('subtitleEditor').then(({default: subtitleEditor}) => { + import('./subtitleeditor/subtitleeditor').then((subtitleEditor) => { subtitleEditor.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }); break; @@ -406,7 +407,7 @@ import actionsheet from 'actionsheet'; editItem(apiClient, item).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); break; case 'editimages': - import('imageEditor').then(({default: imageEditor}) => { + import('./imageeditor/imageeditor').then((imageEditor) => { imageEditor.show({ itemId: itemId, serverId: serverId @@ -414,12 +415,12 @@ import actionsheet from 'actionsheet'; }); break; case 'identify': - import('itemIdentifier').then(({default: itemIdentifier}) => { + import('./itemidentifier/itemidentifier').then((itemIdentifier) => { itemIdentifier.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }); break; case 'moremediainfo': - import('itemMediaInfo').then(({default: itemMediaInfo}) => { + import('./itemMediaInfo/itemMediaInfo').then((itemMediaInfo) => { itemMediaInfo.show(itemId, serverId).then(getResolveFunction(resolve, id), getResolveFunction(resolve, id)); }); break; @@ -454,7 +455,7 @@ import actionsheet from 'actionsheet'; playbackManager.clearQueue(); break; case 'record': - import('recordingCreator').then(({default: recordingCreator}) => { + import('./recordingcreator/recordingcreator').then((recordingCreator) => { recordingCreator.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }); break; @@ -525,7 +526,7 @@ import actionsheet from 'actionsheet'; } function deleteTimer(apiClient, item, resolve, command) { - import('recordingHelper').then(({default: recordingHelper}) => { + import('./recordingcreator/recordinghelper').then((recordingHelper) => { const timerId = item.TimerId || item.Id; recordingHelper.cancelTimerWithConfirmation(timerId, item.ServerId).then(function () { getResolveFunction(resolve, command, true)(); @@ -534,7 +535,7 @@ import actionsheet from 'actionsheet'; } function deleteSeriesTimer(apiClient, item, resolve, command) { - import('recordingHelper').then(({default: recordingHelper}) => { + import('./recordingcreator/recordinghelper').then((recordingHelper) => { recordingHelper.cancelSeriesTimerWithConfirmation(item.Id, item.ServerId).then(function () { getResolveFunction(resolve, command, true)(); }); @@ -568,15 +569,15 @@ import actionsheet from 'actionsheet'; const serverId = apiClient.serverInfo().Id; if (item.Type === 'Timer') { - import('recordingEditor').then(({default: recordingEditor}) => { + import('./recordingcreator/recordingeditor').then((recordingEditor) => { recordingEditor.show(item.Id, serverId).then(resolve, reject); }); } else if (item.Type === 'SeriesTimer') { - import('seriesRecordingEditor').then(({default: recordingEditor}) => { + import('./recordingcreator/seriesrecordingeditor').then((recordingEditor) => { recordingEditor.show(item.Id, serverId).then(resolve, reject); }); } else { - import('metadataEditor').then(({default: metadataEditor}) => { + import('./metadataEditor/metadataEditor').then((metadataEditor) => { metadataEditor.show(item.Id, serverId).then(resolve, reject); }); } @@ -585,7 +586,7 @@ import actionsheet from 'actionsheet'; function deleteItem(apiClient, item) { return new Promise(function (resolve, reject) { - import('deleteHelper').then(({default: deleteHelper}) => { + import('../scripts/deleteHelper').then((deleteHelper) => { deleteHelper.deleteItem({ item: item, navigate: false @@ -597,7 +598,7 @@ import actionsheet from 'actionsheet'; } function refresh(apiClient, item) { - import('refreshDialog').then(({default: refreshDialog}) => { + import('./refreshdialog/refreshdialog').then((refreshDialog) => { new refreshDialog({ itemIds: [item.Id], serverId: apiClient.serverInfo().Id, diff --git a/src/components/itemHelper.js b/src/components/itemHelper.js index 7d1ac0e110..b6f30d7abd 100644 --- a/src/components/itemHelper.js +++ b/src/components/itemHelper.js @@ -1,5 +1,5 @@ -import appHost from 'apphost'; -import globalize from 'globalize'; +import appHost from './apphost'; +import globalize from '../scripts/globalize'; export function getDisplayName(item, options = {}) { if (!item) { diff --git a/src/components/itemMediaInfo/itemMediaInfo.js b/src/components/itemMediaInfo/itemMediaInfo.js index bd3a157dab..9e036fba9a 100644 --- a/src/components/itemMediaInfo/itemMediaInfo.js +++ b/src/components/itemMediaInfo/itemMediaInfo.js @@ -5,17 +5,18 @@ * @module components/itemMediaInfo/itemMediaInfo */ -import dialogHelper from 'dialogHelper'; -import layoutManager from 'layoutManager'; -import globalize from 'globalize'; -import loading from 'loading'; -import 'emby-select'; -import 'listViewStyle'; -import 'paper-icon-button-light'; -import 'css!./../formdialog'; -import 'material-icons'; -import 'emby-button'; -import 'flexStyles'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import layoutManager from '../layoutManager'; +import globalize from '../../scripts/globalize'; +import connectionManager from 'jellyfin-apiclient'; +import loading from '../loading/loading'; +import '../../elements/emby-select/emby-select'; +import '../listview/listview.css'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../formdialog.css'; +import 'material-design-icons-iconfont'; +import '../../assets/css/flexstyles.css'; function setMediaInfo(user, page, item) { let html = item.MediaSources.map(version => { @@ -193,7 +194,7 @@ import 'flexStyles'; export function show(itemId, serverId) { loading.show(); - return import('text!./itemMediaInfo.template.html').then(({default: template}) => { + return import('./itemMediaInfo.template.html').then(({default: template}) => { return new Promise((resolve, reject) => { loadMediaInfo(itemId, serverId, template).then(resolve, reject); }); diff --git a/src/components/itemidentifier/itemidentifier.js b/src/components/itemidentifier/itemidentifier.js index 956cbb4f64..77b04a1a51 100644 --- a/src/components/itemidentifier/itemidentifier.js +++ b/src/components/itemidentifier/itemidentifier.js @@ -5,19 +5,20 @@ * @module components/itemidentifier/itemidentifier */ -import dialogHelper from 'dialogHelper'; -import loading from 'loading'; -import globalize from 'globalize'; -import scrollHelper from 'scrollHelper'; -import layoutManager from 'layoutManager'; -import focusManager from 'focusManager'; -import browser from 'browser'; -import 'emby-input'; -import 'emby-checkbox'; -import 'paper-icon-button-light'; -import 'css!./../formdialog'; -import 'material-icons'; -import 'cardStyle'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import loading from '../loading/loading'; +import connectionManager from 'jellyfin-apiclient'; +import globalize from '../../scripts/globalize'; +import scrollHelper from '../../scripts/scrollHelper'; +import layoutManager from '../layoutManager'; +import focusManager from '../focusManager'; +import browser from '../../scripts/browser'; +import '../../elements/emby-input/emby-input'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../formdialog.css'; +import 'material-design-icons-iconfont'; +import '../cardbuilder/card.css'; const enableFocusTransform = !browser.slow && !browser.edge; @@ -67,7 +68,7 @@ import 'cardStyle'; } if (!hasId && !lookupInfo.Name) { - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('PleaseEnterNameOrId')); }); return; @@ -334,7 +335,7 @@ import 'cardStyle'; function showEditor(itemId) { loading.show(); - return import('text!./itemidentifier.template.html').then(({default: template}) => { + return import('./itemidentifier.template.html').then(({default: template}) => { const apiClient = getApiClient(); apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(item => { @@ -416,7 +417,7 @@ import 'cardStyle'; currentItem = null; currentItemType = itemType; - return import('text!./itemidentifier.template.html').then(({default: template}) => { + return import('./itemidentifier.template.html').then(({default: template}) => { const dialogOptions = { size: 'small', removeOnClose: true, diff --git a/src/components/itemsrefresher.js b/src/components/itemsrefresher.js index 3883e6e490..d283619990 100644 --- a/src/components/itemsrefresher.js +++ b/src/components/itemsrefresher.js @@ -1,6 +1,6 @@ -import playbackManager from 'playbackManager'; -import serverNotifications from 'serverNotifications'; -import events from 'events'; +import playbackManager from './playback/playbackmanager'; +import serverNotifications from '../scripts/serverNotifications'; +import events from 'jellyfin-apiclient'; function onUserDataChanged(e, apiClient, userData) { const instance = this; diff --git a/src/components/layoutManager.js b/src/components/layoutManager.js index fe42583662..c5555d0eb5 100644 --- a/src/components/layoutManager.js +++ b/src/components/layoutManager.js @@ -1,7 +1,7 @@ import appHost from './apphost'; import browser from '../scripts/browser'; import { set, get } from '../scripts/settings/appSettings'; -import events from 'events'; +import events from 'jellyfin-apiclient'; function setLayout(instance, layout, selectedLayout) { if (layout === selectedLayout) { diff --git a/src/components/libraryoptionseditor/libraryoptionseditor.js b/src/components/libraryoptionseditor/libraryoptionseditor.js index 91dbe5ab9e..cdc4f6a28e 100644 --- a/src/components/libraryoptionseditor/libraryoptionseditor.js +++ b/src/components/libraryoptionseditor/libraryoptionseditor.js @@ -5,11 +5,11 @@ * @module components/libraryoptionseditor/libraryoptionseditor */ -import globalize from 'globalize'; -import dom from 'dom'; -import 'emby-checkbox'; -import 'emby-select'; -import 'emby-input'; +import globalize from '../../scripts/globalize'; +import dom from '../../scripts/dom'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-select/emby-select'; +import '../../elements/emby-input/emby-input'; function populateLanguages(parent) { return ApiClient.getCultures().then(languages => { @@ -306,7 +306,7 @@ import 'emby-input'; } function showImageOptionsForType(type) { - import('imageoptionseditor').then(({default: ImageOptionsEditor}) => { + import('../imageOptionsEditor/imageOptionsEditor').then(({default: ImageOptionsEditor}) => { let typeOptions = getTypeOptions(currentLibraryOptions, type); if (!typeOptions) { typeOptions = { diff --git a/src/components/listview/listview.js b/src/components/listview/listview.js index e0fbc2fd2e..33bbdc756c 100644 --- a/src/components/listview/listview.js +++ b/src/components/listview/listview.js @@ -5,16 +5,17 @@ * @module components/listview/listview */ -import itemHelper from 'itemHelper'; -import mediaInfo from 'mediaInfo'; -import indicators from 'indicators'; -import layoutManager from 'layoutManager'; -import globalize from 'globalize'; -import datetime from 'datetime'; -import cardBuilder from 'cardBuilder'; -import 'css!./listview'; -import 'emby-ratingbutton'; -import 'emby-playstatebutton'; +import itemHelper from '../itemHelper'; +import mediaInfo from '../mediainfo/mediainfo'; +import indicators from '../indicators/indicators'; +import connectionManager from 'jellyfin-apiclient'; +import layoutManager from '../layoutManager'; +import globalize from '../../scripts/globalize'; +import datetime from '../../scripts/datetime'; +import cardBuilder from '../cardbuilder/cardBuilder'; +import './listview.css'; +import '../../elements/emby-ratingbutton/emby-ratingbutton'; +import '../../elements/emby-playstatebutton/emby-playstatebutton'; function getIndex(item, options) { if (options.index === 'disc') { diff --git a/src/components/loading/loading.js b/src/components/loading/loading.js index 8237611373..c91cd8beb0 100644 --- a/src/components/loading/loading.js +++ b/src/components/loading/loading.js @@ -1,4 +1,4 @@ -import 'css!./loading'; +import './loading'; let loadingElem; let layer1; diff --git a/src/components/maintabsmanager.js b/src/components/maintabsmanager.js index 1be1cf622f..07a1502823 100644 --- a/src/components/maintabsmanager.js +++ b/src/components/maintabsmanager.js @@ -1,8 +1,8 @@ -import dom from 'dom'; -import browser from 'browser'; -import events from 'events'; -import 'emby-tabs'; -import 'emby-button'; +import dom from '../scripts/dom'; +import browser from '../scripts/browser'; +import events from 'jellyfin-apiclient'; +import '../elements/emby-tabs/emby-tabs'; +import '../elements/emby-button/emby-button'; /* eslint-disable indent */ @@ -65,7 +65,7 @@ import 'emby-button'; } }; - import('touchHelper').then(({default: TouchHelper}) => { + import('../scripts/touchHelper').then((TouchHelper) => { const touchHelper = new TouchHelper(view.parentNode.parentNode); events.on(touchHelper, 'swipeleft', onSwipeLeft); diff --git a/src/components/mediaLibraryCreator/mediaLibraryCreator.js b/src/components/mediaLibraryCreator/mediaLibraryCreator.js index 4e0d7b026c..f3141ebeec 100644 --- a/src/components/mediaLibraryCreator/mediaLibraryCreator.js +++ b/src/components/mediaLibraryCreator/mediaLibraryCreator.js @@ -5,20 +5,20 @@ * @module components/mediaLibraryCreator/mediaLibraryCreator */ -import loading from 'loading'; -import dialogHelper from 'dialogHelper'; -import dom from 'dom'; -import $ from 'jQuery'; -import libraryoptionseditor from 'components/libraryoptionseditor/libraryoptionseditor'; -import globalize from 'globalize'; -import 'emby-toggle'; -import 'emby-input'; -import 'emby-select'; -import 'paper-icon-button-light'; -import 'listViewStyle'; -import 'formDialogStyle'; -import 'emby-button'; -import 'flexStyles'; +import loading from '../loading/loading'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import dom from '../../scripts/dom'; +import 'jquery'; +import libraryoptionseditor from '../libraryoptionseditor/libraryoptionseditor'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-input/emby-input'; +import '../../elements/emby-select/emby-select'; +import '../../elements/emby-toggle/emby-toggle'; +import '../listview/listview.css'; +import '../formdialog.css'; +import '../../assets/css/flexstyles.css'; function onAddLibrary() { if (isCreating) { @@ -26,7 +26,7 @@ import 'flexStyles'; } if (pathInfos.length == 0) { - import('alert').then(({default: alert}) => { + import('../alert').then((alert) => { alert({ text: globalize.translate('PleaseAddAtLeastOneFolder'), type: 'error' @@ -54,7 +54,7 @@ import 'flexStyles'; loading.hide(); dialogHelper.close(dlg); }, () => { - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('ErrorAddingMediaPathToVirtualFolder')); }); @@ -109,7 +109,7 @@ import 'flexStyles'; function onAddButtonClick() { const page = dom.parentWithClass(this, 'dlg-librarycreator'); - import('directorybrowser').then(({default: directoryBrowser}) => { + import('../directorybrowser/directorybrowser').then((directoryBrowser) => { const picker = new directoryBrowser(); picker.show({ enableNetworkSharePath: true, @@ -200,7 +200,7 @@ export class showEditor { currentOptions = options; currentResolve = resolve; hasChanges = false; - import('text!./components/mediaLibraryCreator/mediaLibraryCreator.template.html').then(({default: template}) => { + import('./mediaLibraryCreator.template.html').then(({default: template}) => { const dlg = dialogHelper.createDialog({ size: 'small', modal: false, diff --git a/src/components/mediaLibraryEditor/mediaLibraryEditor.js b/src/components/mediaLibraryEditor/mediaLibraryEditor.js index 13d264f4c9..15f01bb7e4 100644 --- a/src/components/mediaLibraryEditor/mediaLibraryEditor.js +++ b/src/components/mediaLibraryEditor/mediaLibraryEditor.js @@ -5,18 +5,18 @@ * @module components/mediaLibraryEditor/mediaLibraryEditor */ -import jQuery from 'jQuery'; -import loading from 'loading'; -import dialogHelper from 'dialogHelper'; -import dom from 'dom'; -import libraryoptionseditor from 'components/libraryoptionseditor/libraryoptionseditor'; -import globalize from 'globalize'; -import 'emby-button'; -import 'listViewStyle'; -import 'paper-icon-button-light'; -import 'formDialogStyle'; -import 'emby-toggle'; -import 'flexStyles'; +import 'jquery'; +import loading from '../loading/loading'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import dom from '../../scripts/dom'; +import libraryoptionseditor from '../libraryoptionseditor/libraryoptionseditor'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-button/emby-button'; +import '../listview/listview.css'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../formdialog.css'; +import '../../elements/emby-toggle/emby-toggle'; +import '../../assets/css/flexstyles.css'; function onEditLibrary() { if (isCreating) { @@ -47,7 +47,7 @@ import 'flexStyles'; hasChanges = true; refreshLibraryFromServer(page); }, () => { - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('ErrorAddingMediaPathToVirtualFolder')); }); }); @@ -62,7 +62,7 @@ import 'flexStyles'; hasChanges = true; refreshLibraryFromServer(page); }, () => { - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('ErrorAddingMediaPathToVirtualFolder')); }); }); @@ -72,7 +72,7 @@ import 'flexStyles'; const button = btnRemovePath; const virtualFolder = currentOptions.library; - import('confirm').then(({default: confirm}) => { + import('../confirm/confirm').then(({default: confirm}) => { confirm({ title: globalize.translate('HeaderRemoveMediaLocation'), text: globalize.translate('MessageConfirmRemoveMediaLocation'), @@ -84,7 +84,7 @@ import 'flexStyles'; hasChanges = true; refreshLibraryFromServer(dom.parentWithClass(button, 'dlg-libraryeditor')); }, () => { - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('ErrorDefault')); }); }); @@ -167,7 +167,7 @@ import 'flexStyles'; } function showDirectoryBrowser(context, originalPath, networkPath) { - import('directorybrowser').then(({default: directoryBrowser}) => { + import('../directorybrowser/directorybrowser').then((directoryBrowser) => { const picker = new directoryBrowser(); picker.show({ enableNetworkSharePath: true, @@ -215,7 +215,7 @@ export class showEditor { currentOptions = options; currentDeferred = deferred; hasChanges = false; - import('text!./components/mediaLibraryEditor/mediaLibraryEditor.template.html').then(({default: template}) => { + import('./mediaLibraryEditor.template.html').then((template) => { const dlg = dialogHelper.createDialog({ size: 'small', modal: false, diff --git a/src/components/mediainfo/mediainfo.js b/src/components/mediainfo/mediainfo.js index d5da29d3bc..270cfae6d6 100644 --- a/src/components/mediainfo/mediainfo.js +++ b/src/components/mediainfo/mediainfo.js @@ -1,12 +1,12 @@ -import datetime from 'datetime'; -import globalize from 'globalize'; -import appRouter from 'appRouter'; -import itemHelper from 'itemHelper'; -import indicators from 'indicators'; -import 'material-icons'; -import 'css!./mediainfo.css'; -import 'programStyles'; -import 'emby-button'; +import datetime from '../../scripts/datetime'; +import globalize from '../../scripts/globalize'; +import appRouter from '../appRouter'; +import itemHelper from '../itemHelper'; +import indicators from '../indicators/indicators'; +import 'material-design-icons-iconfont'; +import './mediainfo.css'; +import '../guide/programs.css'; +import '../../elements/emby-button/emby-button'; /* eslint-disable indent */ function getTimerIndicator(item) { diff --git a/src/components/metadataEditor/metadataEditor.js b/src/components/metadataEditor/metadataEditor.js index b768e77c4f..32a0a3751f 100644 --- a/src/components/metadataEditor/metadataEditor.js +++ b/src/components/metadataEditor/metadataEditor.js @@ -1,21 +1,22 @@ -import dom from 'dom'; -import layoutManager from 'layoutManager'; -import dialogHelper from 'dialogHelper'; -import datetime from 'datetime'; -import loading from 'loading'; -import focusManager from 'focusManager'; -import globalize from 'globalize'; -import shell from 'shell'; -import 'emby-checkbox'; -import 'emby-input'; -import 'emby-select'; -import 'listViewStyle'; -import 'emby-textarea'; -import 'emby-button'; -import 'paper-icon-button-light'; -import 'css!./../formdialog'; -import 'clearButtonStyle'; -import 'flexStyles'; +import dom from '../../scripts/dom'; +import layoutManager from '../layoutManager'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import datetime from '../../scripts/datetime'; +import loading from '../loading/loading'; +import focusManager from '../focusManager'; +import connectionManager from 'jellyfin-apiclient'; +import globalize from '../../scripts/globalize'; +import shell from '../../scripts/shell'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-input/emby-input'; +import '../../elements/emby-select/emby-select'; +import '../listview/listview.css'; +import '../../elements/emby-textarea/emby-textarea'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../formdialog.css'; +import '../../assets/css/clearbutton.css'; +import '../../assets/css/flexstyles.css'; /* eslint-disable indent */ @@ -35,7 +36,7 @@ import 'flexStyles'; function submitUpdatedItem(form, item) { function afterContentTypeUpdated() { - import('toast').then(({default: toast}) => { + import('../toast/toast').then(({default: toast}) => { toast(globalize.translate('MessageItemSaved')); }); @@ -207,7 +208,7 @@ import 'flexStyles'; } function addElementToList(source, sortCallback) { - import('prompt').then(({default: prompt}) => { + import('../prompt/prompt').then(({default: prompt}) => { prompt({ label: 'Value:' }).then(function (text) { @@ -225,7 +226,7 @@ import 'flexStyles'; } function editPerson(context, person, index) { - import('personEditor').then(({default: personEditor}) => { + import('./personEditor').then((personEditor) => { personEditor.show(person).then(function (updatedPerson) { const isNew = index === -1; @@ -244,14 +245,14 @@ import 'flexStyles'; if (parentId) { reload(context, parentId, item.ServerId); } else { - import('appRouter').then(({default: appRouter}) => { + import('../appRouter').then((appRouter) => { appRouter.goHome(); }); } } function showMoreMenu(context, button, user) { - import('itemContextMenu').then(({default: itemContextMenu}) => { + import('../itemContextMenu').then(({default: itemContextMenu}) => { const item = currentItem; itemContextMenu.show({ @@ -1020,7 +1021,7 @@ import 'flexStyles'; } function centerFocus(elem, horiz, on) { - import('scrollHelper').then(({default: scrollHelper}) => { + import('../../scripts/scrollHelper').then((scrollHelper) => { const fn = on ? 'on' : 'off'; scrollHelper.centerFocus[fn](elem, horiz); }); @@ -1029,7 +1030,7 @@ import 'flexStyles'; function show(itemId, serverId, resolve, reject) { loading.show(); - import('text!./metadataEditor.template.html').then(({default: template}) => { + import('./metadataEditor.template.html').then(({default: template}) => { const dialogOptions = { removeOnClose: true, scrollY: false @@ -1084,7 +1085,7 @@ import 'flexStyles'; return new Promise(function (resolve, reject) { loading.show(); - import('text!./metadataEditor.template.html').then(({default: template}) => { + import('./metadataEditor.template.html').then(({default: template}) => { elem.innerHTML = globalize.translateHtml(template, 'core'); elem.querySelector('.formDialogFooter').classList.remove('formDialogFooter'); diff --git a/src/components/metadataEditor/personEditor.js b/src/components/metadataEditor/personEditor.js index 8326971247..f64f7330d7 100644 --- a/src/components/metadataEditor/personEditor.js +++ b/src/components/metadataEditor/personEditor.js @@ -1,15 +1,16 @@ -import dialogHelper from 'dialogHelper'; -import layoutManager from 'layoutManager'; -import globalize from 'globalize'; -import 'paper-icon-button-light'; -import 'emby-input'; -import 'emby-select'; -import 'css!./../formdialog'; + +import dialogHelper from '../dialogHelper/dialogHelper'; +import layoutManager from '../layoutManager'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-input/emby-input'; +import '../../elements/emby-select/emby-select'; +import '../formdialog.css'; /* eslint-disable indent */ function centerFocus(elem, horiz, on) { - import('scrollHelper').then(({default: scrollHelper}) => { + import('../../scripts/scrollHelper').then((scrollHelper) => { const fn = on ? 'on' : 'off'; scrollHelper.centerFocus[fn](elem, horiz); }); @@ -17,7 +18,7 @@ import 'css!./../formdialog'; function show(person) { return new Promise(function (resolve, reject) { - import('text!./personEditor.template.html').then(({default: template}) => { + import('./personEditor.template.html').then(({default: template}) => { const dialogOptions = { removeOnClose: true, scrollY: false diff --git a/src/components/multiSelect/multiSelect.css b/src/components/multiSelect/multiSelect.css index e9c66c57a4..39b50aa17e 100644 --- a/src/components/multiSelect/multiSelect.css +++ b/src/components/multiSelect/multiSelect.css @@ -1,3 +1,4 @@ + .itemSelectionPanel { position: absolute; bottom: 0; diff --git a/src/components/multiSelect/multiSelect.js b/src/components/multiSelect/multiSelect.js index e7ce440f06..52182d4403 100644 --- a/src/components/multiSelect/multiSelect.js +++ b/src/components/multiSelect/multiSelect.js @@ -1,9 +1,10 @@ -import browser from 'browser'; -import appHost from 'apphost'; -import loading from 'loading'; -import globalize from 'globalize'; -import dom from 'dom'; -import 'css!./multiSelect'; +import browser from '../../scripts/browser'; +import appHost from '../apphost'; +import loading from '../loading/loading'; +import connectionManager from 'jellyfin-apiclient'; +import globalize from '../../scripts/globalize'; +import dom from '../../scripts/dom'; +import './multiSelect.css'; /* eslint-disable indent */ @@ -138,7 +139,7 @@ import 'css!./multiSelect'; function alertText(options) { return new Promise((resolve, reject) => { - import('alert').then(({default: alert}) => { + import('../alert').then((alert) => { alert(options).then(resolve, resolve); }); }); @@ -154,7 +155,7 @@ import 'css!./multiSelect'; title = globalize.translate('HeaderDeleteItems'); } - import('confirm').then(({default: confirm}) => { + import('../confirm/confirm').then((confirm) => { confirm(msg, title).then(() => { const promises = itemIds.map(itemId => { apiClient.deleteItem(itemId); @@ -229,7 +230,7 @@ import 'css!./multiSelect'; icon: 'refresh' }); - import('actionsheet').then(({default: actionsheet}) => { + import('../actionSheet/actionSheet').then((actionsheet) => { actionsheet.show({ items: menuItems, positionTo: e.target, @@ -239,7 +240,7 @@ import 'css!./multiSelect'; switch (id) { case 'addtocollection': - import('collectionEditor').then(({default: collectionEditor}) => { + import('../collectionEditor/collectionEditor').then((collectionEditor) => { new collectionEditor({ items: items, serverId: serverId @@ -249,7 +250,7 @@ import 'css!./multiSelect'; dispatchNeedsRefresh(); break; case 'playlist': - import('playlistEditor').then(({default: playlistEditor}) => { + import('../playlisteditor/playlisteditor').then((laylistEditor) => { new playlistEditor({ items: items, serverId: serverId @@ -281,7 +282,7 @@ import 'css!./multiSelect'; dispatchNeedsRefresh(); break; case 'refresh': - import('refreshDialog').then(({default: refreshDialog}) => { + import('../refreshdialog/refreshdialog').then((refreshDialog) => { new refreshDialog({ itemIds: items, serverId: serverId @@ -317,7 +318,7 @@ import 'css!./multiSelect'; function combineVersions(apiClient, selection) { if (selection.length < 2) { - import('alert').then(({default: alert}) => { + import('../alert').then((alert) => { alert({ text: globalize.translate('PleaseSelectTwoItems') @@ -341,7 +342,7 @@ import 'css!./multiSelect'; } function showSelections(initialCard) { - import('emby-checkbox').then(() => { + import('../../elements/emby-checkbox/emby-checkbox').then(() => { const cards = document.querySelectorAll('.card'); for (let i = 0, length = cards.length; i < length; i++) { showSelection(cards[i], initialCard === cards[i]); diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js index 7f0e68f1d9..1eca2c3807 100644 --- a/src/components/notifications/notifications.js +++ b/src/components/notifications/notifications.js @@ -1,7 +1,7 @@ -import serverNotifications from 'serverNotifications'; -import playbackManager from 'playbackManager'; -import events from 'events'; -import globalize from 'globalize'; +import serverNotifications from '../../scripts/serverNotifications'; +import playbackManager from '../playback/playbackmanager'; +import events from 'jellyfin-apiclient'; +import globalize from '../../scripts/globalize'; function onOneDocumentClick() { document.removeEventListener('click', onOneDocumentClick); diff --git a/src/components/nowPlayingBar/nowPlayingBar.js b/src/components/nowPlayingBar/nowPlayingBar.js index 40337d51e0..9607fadcb1 100644 --- a/src/components/nowPlayingBar/nowPlayingBar.js +++ b/src/components/nowPlayingBar/nowPlayingBar.js @@ -1,15 +1,16 @@ -import datetime from 'datetime'; -import events from 'events'; -import browser from 'browser'; -import imageLoader from 'imageLoader'; -import layoutManager from 'layoutManager'; -import playbackManager from 'playbackManager'; -import nowPlayingHelper from 'nowPlayingHelper'; -import appHost from 'apphost'; -import dom from 'dom'; -import itemContextMenu from 'itemContextMenu'; -import 'paper-icon-button-light'; -import 'emby-ratingbutton'; +import datetime from '../../scripts/datetime'; +import events from 'jellyfin-apiclient'; +import browser from '../../scripts/browser'; +import imageLoader from '../../scripts/imagehelper'; +import layoutManager from '../layoutManager'; +import playbackManager from '../playback/playbackmanager'; +import nowPlayingHelper from '../playback/nowplayinghelper'; +import appHost from '../apphost'; +import dom from '../../scripts/dom'; +import connectionManager from 'jellyfin-apiclient'; +import itemContextMenu from '../itemContextMenu'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-ratingbutton/emby-ratingbutton'; /* eslint-disable indent */ @@ -243,7 +244,7 @@ import 'emby-ratingbutton'; } function showRemoteControl() { - import('appRouter').then(({default: appRouter}) => { + import('../appRouter').then(({default: appRouter}) => { appRouter.showNowPlaying(); }); } @@ -256,10 +257,10 @@ import 'emby-ratingbutton'; return new Promise(function (resolve, reject) { Promise.all([ - import('appFooter'), - import('itemShortcuts'), - import('css!./nowPlayingBar.css'), - import('emby-slider') + import('../appFooter/appFooter'), + import('../shortcuts'), + import('./nowPlayingBar.css'), + import('../../elements/emby-slider/emby-slider') ]) .then(([appfooter, itemShortcuts]) => { const parentContainer = appfooter.element; diff --git a/src/components/packageManager.js b/src/components/packageManager.js index c4b4701e9d..0fd5bb7502 100644 --- a/src/components/packageManager.js +++ b/src/components/packageManager.js @@ -1,5 +1,5 @@ -import appSettings from 'appSettings'; -import pluginManager from 'pluginManager'; +import appSettings from '../scripts/settings/appSettings'; +import pluginManager from './pluginManager'; /* eslint-disable indent */ class PackageManager { diff --git a/src/components/playback/brightnessosd.js b/src/components/playback/brightnessosd.js index 78c40d10c1..935656e230 100644 --- a/src/components/playback/brightnessosd.js +++ b/src/components/playback/brightnessosd.js @@ -1,9 +1,9 @@ -import events from 'events'; -import playbackManager from 'playbackManager'; -import dom from 'dom'; -import browser from 'browser'; -import 'css!./iconosd'; -import 'material-icons'; +import events from 'jellyfin-apiclient'; +import playbackManager from './playbackmanager'; +import dom from '../../scripts/dom'; +import browser from '../../scripts/browser'; +import './iconosd.css'; +import 'material-design-icons-iconfont'; let currentPlayer; let osdElement; diff --git a/src/components/playback/mediasession.js b/src/components/playback/mediasession.js index b75fa69a8c..52ef5c36ed 100644 --- a/src/components/playback/mediasession.js +++ b/src/components/playback/mediasession.js @@ -1,7 +1,7 @@ -import playbackManager from 'playbackManager'; -import nowPlayingHelper from 'nowPlayingHelper'; -import shell from 'shell'; -import events from 'events'; +import playbackManager from '../playback/playbackmanager'; +import nowPlayingHelper from '../playback/nowplayinghelper'; +import events from 'jellyfin-apiclient'; +import connectionManager from 'jellyfin-apiclient'; /* eslint-disable indent */ // Reports media playback to the device for lock screen control diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 6fcc05ea63..af60dd61dd 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -1,13 +1,14 @@ -import events from 'events'; -import datetime from 'datetime'; -import appSettings from 'appSettings'; -import itemHelper from 'itemHelper'; -import pluginManager from 'pluginManager'; -import PlayQueueManager from 'playQueueManager'; -import * as userSettings from 'userSettings'; -import globalize from 'globalize'; -import loading from 'loading'; -import appHost from 'apphost'; +import events from 'jellyfin-apiclient'; +import datetime from '../../scripts/datetime'; +import appSettings from '../../scripts/settings/appSettings'; +import itemHelper from '../itemHelper'; +import pluginManager from '../pluginManager'; +import PlayQueueManager from './playqueuemanager'; +import * as userSettings from '../../scripts/settings/userSettings'; +import globalize from '../../scripts/globalize'; +import connectionManager from 'jellyfin-apiclient'; +import loading from '../loading/loading'; +import appHost from '../apphost'; import screenfull from 'screenfull'; function enableLocalPlaylistManagement(player) { @@ -619,7 +620,7 @@ function supportsDirectPlay(apiClient, item, mediaSource) { } else if (mediaSource.Protocol === 'File') { return new Promise(function (resolve, reject) { // Determine if the file can be accessed directly - import('filesystem').then((filesystem) => { + import('../../scripts/filesystem').then((filesystem) => { const method = isFolderRip ? 'directoryExists' : 'fileExists'; @@ -647,7 +648,7 @@ function validatePlaybackInfoResult(instance, result) { } function showPlaybackInfoErrorMessage(instance, errorCode) { - import('alert').then(({ default: alert }) => { + import('../alert').then(({ default: alert }) => { alert({ text: globalize.translate(errorCode), title: globalize.translate('HeaderPlaybackError') @@ -1161,7 +1162,7 @@ class PlaybackManager { if (!brightnessOsdLoaded) { brightnessOsdLoaded = true; // TODO: Have this trigger an event instead to get the osd out of here - import('brightnessOsd').then(); + import('./brightnessosd').then(); } player.setBrightness(val); } @@ -3190,7 +3191,7 @@ class PlaybackManager { }; if (appHost.supports('remotecontrol')) { - import('serverNotifications').then(({ default: serverNotifications }) => { + import('../../scripts/serverNotifications').then((serverNotifications) => { events.on(serverNotifications, 'ServerShuttingDown', self.setDefaultPlayerActive.bind(self)); events.on(serverNotifications, 'ServerRestarting', self.setDefaultPlayerActive.bind(self)); }); diff --git a/src/components/playback/playbackorientation.js b/src/components/playback/playbackorientation.js index f585f25ae1..6c44d5bbca 100644 --- a/src/components/playback/playbackorientation.js +++ b/src/components/playback/playbackorientation.js @@ -1,6 +1,7 @@ -import playbackManager from 'playbackManager'; -import layoutManager from 'layoutManager'; -import events from 'events'; + +import playbackManager from './playbackmanager'; +import layoutManager from '../layoutManager'; +import events from 'jellyfin-apiclient'; let orientationLocked; diff --git a/src/components/playback/playerSelectionMenu.js b/src/components/playback/playerSelectionMenu.js index 38ff399a9e..1bd9090254 100644 --- a/src/components/playback/playerSelectionMenu.js +++ b/src/components/playback/playerSelectionMenu.js @@ -1,12 +1,12 @@ -import appSettings from 'appSettings'; -import events from 'events'; -import browser from 'browser'; -import loading from 'loading'; -import playbackManager from 'playbackManager'; -import appRouter from 'appRouter'; -import globalize from 'globalize'; -import appHost from 'apphost'; -import * as autocast from 'autocast'; +import appSettings from '../../scripts/settings/appSettings'; +import events from 'jellyfin-apiclient'; +import browser from '../../scripts/browser'; +import loading from '../loading/loading'; +import playbackManager from '../playback/playbackmanager'; +import appRouter from '../appRouter'; +import globalize from '../../scripts/globalize'; +import appHost from '../apphost'; +import { enable, isEnabled, supported } from '../../scripts/autocast'; function mirrorItem(info, player) { const item = info.item; @@ -108,7 +108,7 @@ export function show(button) { }; }); - import('actionsheet').then(({default: actionsheet}) => { + import('../actionSheet/actionSheet').then((actionsheet) => { loading.hide(); const menuOptions = { @@ -141,10 +141,10 @@ export function show(button) { function showActivePlayerMenu(playerInfo) { Promise.all([ - import('dialogHelper'), - import('dialog'), - import('emby-checkbox'), - import('emby-button') + import('../dialogHelper/dialogHelper'), + import('../dialog/dialog'), + import('../../elements/emby-checkbox/emby-checkbox'), + import('../../elements/emby-button/emby-button') ]).then(([dialogHelper]) => { showActivePlayerMenuInternal(dialogHelper, playerInfo); }); @@ -152,7 +152,7 @@ function showActivePlayerMenu(playerInfo) { function disconnectFromPlayer(currentDeviceName) { if (playbackManager.getSupportedCommands().indexOf('EndSession') !== -1) { - import('dialog').then(({default: dialog}) => { + import('../dialog/dialog').then(({default: dialog}) => { const menuItems = []; menuItems.push({ @@ -222,9 +222,9 @@ function showActivePlayerMenuInternal(dialogHelper, playerInfo) { html += '
'; - if (autocast.supported()) { + if (supported()) { html += '
'; @@ -285,7 +285,7 @@ function onMirrorChange() { } function onAutoCastChange() { - autocast.enable(this.checked); + enable(this.checked); } document.addEventListener('viewshow', function (e) { diff --git a/src/components/playback/playersettingsmenu.js b/src/components/playback/playersettingsmenu.js index 40819f62ea..acec830912 100644 --- a/src/components/playback/playersettingsmenu.js +++ b/src/components/playback/playersettingsmenu.js @@ -1,7 +1,8 @@ -import actionsheet from 'actionsheet'; -import playbackManager from 'playbackManager'; -import globalize from 'globalize'; -import qualityoptions from 'qualityoptions'; +import connectionManager from 'jellyfin-apiclient'; +import actionsheet from '../actionSheet/actionSheet'; +import playbackManager from '../playback/playbackmanager'; +import globalize from '../../scripts/globalize'; +import qualityoptions from '../qualityOptions'; function showQualityMenu(player, btn) { const videoStream = playbackManager.currentMediaSource(player).MediaStreams.filter(function (stream) { diff --git a/src/components/playback/remotecontrolautoplay.js b/src/components/playback/remotecontrolautoplay.js index c0adb57a45..532a71237d 100644 --- a/src/components/playback/remotecontrolautoplay.js +++ b/src/components/playback/remotecontrolautoplay.js @@ -1,5 +1,5 @@ -import events from 'events'; -import playbackManager from 'playbackManager'; +import events from 'jellyfin-apiclient'; +import playbackManager from '../playback/playbackmanager'; function transferPlayback(oldPlayer, newPlayer) { const state = playbackManager.getPlayerState(oldPlayer); diff --git a/src/components/playback/volumeosd.js b/src/components/playback/volumeosd.js index c35914b192..9e84017838 100644 --- a/src/components/playback/volumeosd.js +++ b/src/components/playback/volumeosd.js @@ -1,9 +1,10 @@ -import events from 'events'; -import playbackManager from 'playbackManager'; -import dom from 'dom'; -import browser from 'browser'; -import 'css!./iconosd'; -import 'material-icons'; + +import events from 'jellyfin-apiclient'; +import playbackManager from './playbackmanager'; +import dom from '../../scripts/dom'; +import browser from '../../scripts/browser'; +import './iconosd.css'; +import 'material-design-icons-iconfont'; let currentPlayer; let osdElement; diff --git a/src/components/playbackSettings/playbackSettings.js b/src/components/playbackSettings/playbackSettings.js index 782e3d38e1..4d123bb738 100644 --- a/src/components/playbackSettings/playbackSettings.js +++ b/src/components/playbackSettings/playbackSettings.js @@ -1,13 +1,14 @@ -import browser from 'browser'; -import appSettings from 'appSettings'; -import appHost from 'apphost'; -import focusManager from 'focusManager'; -import qualityoptions from 'qualityoptions'; -import globalize from 'globalize'; -import loading from 'loading'; -import events from 'events'; -import 'emby-select'; -import 'emby-checkbox'; +import browser from '../../scripts/browser'; +import appSettings from '../../scripts/settings/appSettings'; +import appHost from '../apphost'; +import focusManager from '../focusManager'; +import qualityoptions from '../qualityOptions'; +import globalize from '../../scripts/globalize'; +import loading from '../loading/loading'; +import connectionManager from 'jellyfin-apiclient'; +import events from 'jellyfin-apiclient'; +import '../../elements/emby-select/emby-select'; +import '../../elements/emby-checkbox/emby-checkbox'; /* eslint-disable indent */ @@ -243,7 +244,7 @@ import 'emby-checkbox'; saveUser(context, user, userSettings, apiClient).then(() => { loading.hide(); if (enableSaveConfirmation) { - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('SettingsSaved')); }); } @@ -274,7 +275,7 @@ import 'emby-checkbox'; } function embed(options, self) { - return import('text!./playbackSettings.template.html').then(({default: template}) => { + return import('./playbackSettings.template.html').then(({default: template}) => { options.element.innerHTML = globalize.translateHtml(template, 'core'); options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self)); diff --git a/src/components/playerstats/playerstats.js b/src/components/playerstats/playerstats.js index e100dee594..59f885f320 100644 --- a/src/components/playerstats/playerstats.js +++ b/src/components/playerstats/playerstats.js @@ -1,11 +1,12 @@ -import events from 'events'; -import globalize from 'globalize'; -import playbackManager from 'playbackManager'; -import syncPlayManager from 'syncPlayManager'; -import playMethodHelper from 'playMethodHelper'; -import layoutManager from 'layoutManager'; -import 'paper-icon-button-light'; -import 'css!./playerstats'; +import connectionManager from 'jellyfin-apiclient'; +import events from 'jellyfin-apiclient'; +import '../../elements/emby-button/paper-icon-button-light'; +import globalize from '../../scripts/globalize'; +import layoutManager from '../layoutManager'; +import playbackManager from '../playback/playbackmanager'; +import playMethodHelper from '../playback/playmethodhelper'; +import syncPlayManager from '../syncPlay/syncPlayManager'; +import './playerstats.css'; /* eslint-disable indent */ diff --git a/src/components/playlisteditor/playlisteditor.js b/src/components/playlisteditor/playlisteditor.js index dda9436a29..a3221ff3c6 100644 --- a/src/components/playlisteditor/playlisteditor.js +++ b/src/components/playlisteditor/playlisteditor.js @@ -1,17 +1,18 @@ -import dom from 'dom'; -import dialogHelper from 'dialogHelper'; -import loading from 'loading'; -import layoutManager from 'layoutManager'; -import playbackManager from 'playbackManager'; -import * as userSettings from 'userSettings'; -import appRouter from 'appRouter'; -import globalize from 'globalize'; -import 'emby-input'; -import 'paper-icon-button-light'; -import 'emby-select'; -import 'material-icons'; -import 'css!./../formdialog'; -import 'emby-button'; +import dom from '../../scripts/dom'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import loading from '../loading/loading'; +import layoutManager from '../layoutManager'; +import playbackManager from '../playback/playbackmanager'; +import connectionManager from 'jellyfin-apiclient'; +import * as userSettings from '../../scripts/settings/userSettings'; +import appRouter from '../appRouter'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-input/emby-input'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-select/emby-select'; +import 'material-design-icons-iconfont'; +import '../formdialog.css'; /* eslint-disable indent */ @@ -209,7 +210,7 @@ import 'emby-button'; } function centerFocus(elem, horiz, on) { - import('scrollHelper').then((scrollHelper) => { + import('../../scripts/scrollHelper').then((scrollHelper) => { const fn = on ? 'on' : 'off'; scrollHelper.centerFocus[fn](elem, horiz); }); diff --git a/src/components/playmenu.js b/src/components/playmenu.js index 57ee5ca6e3..8831b4d7b7 100644 --- a/src/components/playmenu.js +++ b/src/components/playmenu.js @@ -1,7 +1,7 @@ -import actionsheet from 'actionsheet'; -import datetime from 'datetime'; -import playbackManager from 'playbackManager'; -import globalize from 'globalize'; +import actionsheet from './actionSheet/actionSheet'; +import datetime from '../scripts/datetime'; +import playbackManager from './playback/playbackmanager'; +import globalize from '../scripts/globalize'; export function show(options) { const item = options.item; diff --git a/src/components/pluginManager.js b/src/components/pluginManager.js index c07c77b736..116281c482 100644 --- a/src/components/pluginManager.js +++ b/src/components/pluginManager.js @@ -1,5 +1,5 @@ -import events from 'events'; -import globalize from 'globalize'; +import events from 'jellyfin-apiclient'; +import globalize from '../scripts/globalize'; /* eslint-disable indent */ // TODO: replace with each plugin version diff --git a/src/components/prompt/prompt.js b/src/components/prompt/prompt.js index 868f1d865c..c2c52bd41c 100644 --- a/src/components/prompt/prompt.js +++ b/src/components/prompt/prompt.js @@ -1,14 +1,14 @@ -import browser from 'browser'; -import dialogHelper from 'dialogHelper'; -import layoutManager from 'layoutManager'; -import scrollHelper from 'scrollHelper'; -import globalize from 'globalize'; -import dom from 'dom'; -import 'material-icons'; -import 'emby-button'; -import 'paper-icon-button-light'; -import 'emby-input'; -import 'formDialogStyle'; +import browser from '../../scripts/browser'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import layoutManager from '../layoutManager'; +import scrollHelper from '../../scripts/scrollHelper'; +import globalize from '../../scripts/globalize'; +import dom from '../../scripts/dom'; +import 'material-design-icons-iconfont'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-input/emby-input'; +import '../formdialog.css'; /* eslint-disable indent */ export default (() => { @@ -117,7 +117,7 @@ export default (() => { } else { return options => { return new Promise((resolve, reject) => { - import('text!./prompt.template.html').then(({default: template}) => { + import('./prompt.template.html').then(({default: template}) => { if (typeof options === 'string') { options = { title: '', diff --git a/src/components/qualityOptions.js b/src/components/qualityOptions.js index 93a8d5fe73..2037cb8ccf 100644 --- a/src/components/qualityOptions.js +++ b/src/components/qualityOptions.js @@ -1,4 +1,4 @@ -import globalize from 'globalize'; +import globalize from '../scripts/globalize'; export function getVideoQualityOptions(options) { const maxStreamingBitrate = options.currentMaxBitrate; diff --git a/src/components/recordingcreator/recordingbutton.js b/src/components/recordingcreator/recordingbutton.js index dc7da836da..a898cf4a5b 100644 --- a/src/components/recordingcreator/recordingbutton.js +++ b/src/components/recordingcreator/recordingbutton.js @@ -1,8 +1,9 @@ -import dom from 'dom'; -import recordingHelper from 'recordingHelper'; -import 'paper-icon-button-light'; -import 'emby-button'; -import 'css!./recordingfields'; +import connectionManager from 'jellyfin-apiclient'; +import dom from '../../scripts/dom'; +import recordingHelper from './recordinghelper'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-button/emby-button'; +import './recordingfields.css'; function onRecordingButtonClick(e) { const item = this.item; diff --git a/src/components/recordingcreator/recordingcreator.js b/src/components/recordingcreator/recordingcreator.js index 27ad0584d5..fe5b506c96 100644 --- a/src/components/recordingcreator/recordingcreator.js +++ b/src/components/recordingcreator/recordingcreator.js @@ -1,22 +1,22 @@ -import dialogHelper from 'dialogHelper'; -import globalize from 'globalize'; -import layoutManager from 'layoutManager'; -import mediaInfo from 'mediaInfo'; -import require from 'require'; -import loading from 'loading'; -import scrollHelper from 'scrollHelper'; -import datetime from 'datetime'; -import imageLoader from 'imageLoader'; -import recordingFields from 'recordingFields'; -import events from 'events'; -import 'emby-checkbox'; -import 'emby-button'; -import 'emby-collapse'; -import 'emby-input'; -import 'paper-icon-button-light'; -import 'css!./../formdialog'; -import 'css!./recordingcreator'; -import 'material-icons'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import globalize from '../../scripts/globalize'; +import layoutManager from '../layoutManager'; +import mediaInfo from '../mediainfo/mediainfo'; +import connectionManager from 'jellyfin-apiclient'; +import loading from '../loading/loading'; +import scrollHelper from '../../scripts/scrollHelper'; +import datetime from '../../scripts/datetime'; +import imageLoader from '../images/imageLoader'; +import recordingFields from './recordingfields'; +import events from 'jellyfin-apiclient'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-collapse/emby-collapse'; +import '../../elements/emby-input/emby-input'; +import '../formdialog.css'; +import './recordingcreator.css'; +import 'material-design-icons-iconfont'; let currentDialog; let closeAction; @@ -68,7 +68,7 @@ function renderRecording(context, defaultTimer, program, apiClient, refreshRecor const imageContainer = context.querySelector('.recordingDialog-imageContainer'); if (imgUrl) { - imageContainer.innerHTML = ''; + imageContainer.innerHTML = ''; imageContainer.classList.remove('hide'); imageLoader.lazyChildren(imageContainer); @@ -117,8 +117,8 @@ function reload(context, programId, serverId, refreshRecordingStateOnly) { function executeCloseAction(action, programId, serverId) { if (action === 'play') { - import('playbackManager').then(({ default: playbackManager }) => { - const apiClient = window.connectionManager.getApiClient(serverId); + import('../playback/playbackmanager').then(({ default: playbackManager }) => { + const apiClient = connectionManager.getApiClient(serverId); apiClient.getLiveTvProgram(programId, apiClient.getCurrentUserId()).then(function (item) { playbackManager.play({ @@ -137,7 +137,7 @@ function showEditor(itemId, serverId) { loading.show(); - import('text!./recordingcreator.template.html').then(({ default: template }) => { + import('./recordingcreator.template.html').then(({ default: template }) => { const dialogOptions = { removeOnClose: true, scrollY: false diff --git a/src/components/recordingcreator/recordingeditor.js b/src/components/recordingcreator/recordingeditor.js index 37b55e4eec..6c5a380d11 100644 --- a/src/components/recordingcreator/recordingeditor.js +++ b/src/components/recordingcreator/recordingeditor.js @@ -1,17 +1,19 @@ -import dialogHelper from 'dialogHelper'; -import globalize from 'globalize'; -import layoutManager from 'layoutManager'; -import loading from 'loading'; -import scrollHelper from 'scrollHelper'; -import 'scrollStyles'; -import 'emby-button'; -import 'emby-collapse'; -import 'emby-input'; -import 'paper-icon-button-light'; -import 'css!./../formdialog'; -import 'css!./recordingcreator'; -import 'material-icons'; -import 'flexStyles'; + +import dialogHelper from '../dialogHelper/dialogHelper'; +import globalize from '../../scripts/globalize'; +import layoutManager from '../layoutManager'; +import connectionManager from 'jellyfin-apiclient'; +import loading from '../loading/loading'; +import scrollHelper from '../../scripts/scrollHelper'; +import '../../assets/css/scrollstyles.css'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-collapse/emby-collapse'; +import '../../elements/emby-input/emby-input'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../formdialog.css'; +import './recordingcreator.css'; +import 'material-design-icons-iconfont'; +import '../../assets/css/flexstyles.css'; let currentDialog; let recordingDeleted = false; @@ -20,7 +22,7 @@ let currentServerId; let currentResolve; function deleteTimer(apiClient, timerId) { - return import('recordingHelper').then(({ default: recordingHelper }) => { + return import('./recordinghelper').then((recordingHelper) => { recordingHelper.cancelTimerWithConfirmation(timerId, apiClient.serverId()); }); } @@ -89,7 +91,7 @@ function showEditor(itemId, serverId, options) { options = options || {}; currentResolve = resolve; - import('text!./recordingeditor.template.html').then(({default: template}) => { + import('./recordingeditor.template.html').then(({default: template}) => { const dialogOptions = { removeOnClose: true, scrollY: false diff --git a/src/components/recordingcreator/recordingfields.js b/src/components/recordingcreator/recordingfields.js index 9b3f0d16a3..39e549ee86 100644 --- a/src/components/recordingcreator/recordingfields.js +++ b/src/components/recordingcreator/recordingfields.js @@ -1,13 +1,14 @@ -import globalize from 'globalize'; -import serverNotifications from 'serverNotifications'; -import loading from 'loading'; -import dom from 'dom'; -import recordingHelper from 'recordingHelper'; -import events from 'events'; -import 'paper-icon-button-light'; -import 'emby-button'; -import 'css!./recordingfields'; -import 'flexStyles'; +import globalize from '../../scripts/globalize'; +import connectionManager from 'jellyfin-apiclient'; +import serverNotifications from '../../scripts/serverNotifications'; +import loading from '../loading/loading'; +import dom from '../../scripts/dom'; +import recordingHelper from './recordinghelper'; +import events from 'jellyfin-apiclient'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-button/paper-icon-button-light'; +import './recordingfields.css'; +import '../../assets/css/flexstyles.css'; /*eslint prefer-const: "error"*/ @@ -117,7 +118,7 @@ class RecordingEditor { embed() { const self = this; return new Promise(function (resolve, reject) { - import('text!./recordingfields.template.html').then(({default: template}) => { + import('./recordingfields.template.html').then(({default: template}) => { const options = self.options; const context = options.parent; context.innerHTML = globalize.translateHtml(template, 'core'); @@ -162,7 +163,7 @@ function onManageRecordingClick(e) { } const self = this; - import('recordingEditor').then(({default: recordingEditor}) => { + import('./recordingeditor').then((recordingEditor) => { recordingEditor.show(self.TimerId, options.serverId, { enableCancel: false }).then(function () { @@ -180,7 +181,7 @@ function onManageSeriesRecordingClick(e) { const self = this; - import('seriesRecordingEditor').then(({default: seriesRecordingEditor}) => { + import('./seriesrecordingeditor').then((seriesRecordingEditor) => { seriesRecordingEditor.show(self.SeriesTimerId, options.serverId, { enableCancel: false @@ -225,7 +226,7 @@ function onRecordChange(e) { } function sendToast(msg) { - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(msg); }); } diff --git a/src/components/recordingcreator/recordinghelper.js b/src/components/recordingcreator/recordinghelper.js index 495378106c..8ba1c4dfef 100644 --- a/src/components/recordingcreator/recordinghelper.js +++ b/src/components/recordingcreator/recordinghelper.js @@ -1,5 +1,6 @@ -import globalize from 'globalize'; -import loading from 'loading'; +import globalize from '../../scripts/globalize'; +import loading from '../loading/loading'; +import connectionManager from 'jellyfin-apiclient'; /*eslint prefer-const: "error"*/ @@ -28,7 +29,7 @@ function changeRecordingToSeries(apiClient, timerId, programId, confirmTimerCanc function cancelTimerWithConfirmation(timerId, serverId) { return new Promise(function (resolve, reject) { - import('confirm').then(({ default: confirm }) => { + import('../confirm/confirm').then((confirm) => { confirm.default({ text: globalize.translate('MessageConfirmRecordingCancellation'), @@ -48,7 +49,7 @@ function cancelTimerWithConfirmation(timerId, serverId) { function cancelSeriesTimerWithConfirmation(timerId, serverId) { return new Promise(function (resolve, reject) { - import('confirm').then(({ default: confirm }) => { + import('../confirm/confirm').then((confirm) => { confirm.default({ text: globalize.translate('MessageConfirmRecordingCancellation'), @@ -61,7 +62,7 @@ function cancelSeriesTimerWithConfirmation(timerId, serverId) { const apiClient = window.connectionManager.getApiClient(serverId); apiClient.cancelLiveTvSeriesTimer(timerId).then(function () { - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('SeriesCancelled')); }); @@ -98,14 +99,14 @@ function createRecording(apiClient, programId, isSeries) { } function sendToast(msg) { - import('toast').then(({ default: toast }) => { + import('../toast/toast').then((toast) => { toast(msg); }); } function showMultiCancellationPrompt(serverId, programId, timerId, timerStatus, seriesTimerId) { return new Promise(function (resolve, reject) { - import('dialog').then(({ default: dialog }) => { + import('../dialog/dialog').then((dialog) => { const items = []; items.push({ @@ -150,7 +151,7 @@ function showMultiCancellationPrompt(serverId, programId, timerId, timerStatus, loading.show(); apiClient.cancelLiveTvSeriesTimer(seriesTimerId).then(function () { - import('toast').then(({ default: toast }) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('SeriesCancelled')); }); diff --git a/src/components/recordingcreator/seriesrecordingeditor.js b/src/components/recordingcreator/seriesrecordingeditor.js index e3a6ae6853..6b887280e6 100644 --- a/src/components/recordingcreator/seriesrecordingeditor.js +++ b/src/components/recordingcreator/seriesrecordingeditor.js @@ -1,19 +1,20 @@ -import dialogHelper from 'dialogHelper'; -import globalize from 'globalize'; -import layoutManager from 'layoutManager'; -import loading from 'loading'; -import scrollHelper from 'scrollHelper'; -import datetime from 'datetime'; -import 'scrollStyles'; -import 'emby-button'; -import 'emby-checkbox'; -import 'emby-input'; -import 'emby-select'; -import 'paper-icon-button-light'; -import 'css!./../formdialog'; -import 'css!./recordingcreator'; -import 'material-icons'; -import 'flexStyles'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import globalize from '../../scripts/globalize'; +import layoutManager from '../layoutManager'; +import connectionManager from 'jellyfin-apiclient'; +import loading from '../loading/loading'; +import scrollHelper from '../../scripts/scrollHelper'; +import datetime from '../../scripts/datetime'; +import '../../assets/css/scrollstyles.css'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-input/emby-input'; +import '../../elements/emby-select/emby-select'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../formdialog.css'; +import './recordingcreator.css'; +import 'material-design-icons-iconfont'; +import '../../assets/css/flexstyles.css'; /*eslint prefer-const: "error"*/ @@ -25,7 +26,7 @@ let currentServerId; function deleteTimer(apiClient, timerId) { return new Promise(function (resolve, reject) { - import('recordingHelper').then(({ default: recordingHelper }) => { + import('./recordinghelper').then((recordingHelper) => { recordingHelper.cancelSeriesTimerWithConfirmation(timerId, apiClient.serverId()).then(resolve, reject); }); }); @@ -150,7 +151,7 @@ function embed(itemId, serverId, options) { loading.show(); options = options || {}; - import('text!./seriesrecordingeditor.template.html').then(({ default: template }) => { + import('./seriesrecordingeditor.template.html').then(({ default: template }) => { const dialogOptions = { removeOnClose: true, scrollY: false @@ -192,7 +193,7 @@ function showEditor(itemId, serverId, options) { loading.show(); options = options || {}; - import('text!./seriesrecordingeditor.template.html').then(({ default: template }) => { + import('./seriesrecordingeditor.template.html').then(({ default: template }) => { const dialogOptions = { removeOnClose: true, scrollY: false diff --git a/src/components/refreshdialog/refreshdialog.js b/src/components/refreshdialog/refreshdialog.js index e5ceb1e6e0..1338e4b722 100644 --- a/src/components/refreshdialog/refreshdialog.js +++ b/src/components/refreshdialog/refreshdialog.js @@ -1,15 +1,16 @@ -import dom from 'dom'; -import dialogHelper from 'dialogHelper'; -import loading from 'loading'; -import layoutManager from 'layoutManager'; -import globalize from 'globalize'; -import 'emby-input'; -import 'emby-checkbox'; -import 'paper-icon-button-light'; -import 'emby-select'; -import 'material-icons'; -import 'css!./../formdialog'; -import 'emby-button'; +import dom from '../../scripts/dom'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import loading from '../loading/loading'; +import layoutManager from '../layoutManager'; +import connectionManager from 'jellyfin-apiclient'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-input/emby-input'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-select/emby-select'; +import 'material-design-icons-iconfont'; +import '../formdialog.css'; /*eslint prefer-const: "error"*/ @@ -52,7 +53,7 @@ function getEditorHtml() { } function centerFocus(elem, horiz, on) { - import('scrollHelper').then(({default: scrollHelper}) => { + import('../../scripts/scrollHelper').then((scrollHelper) => { const fn = on ? 'on' : 'off'; scrollHelper.centerFocus[fn](elem, horiz); }); @@ -85,7 +86,7 @@ function onSubmit(e) { dialogHelper.close(dlg); - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('RefreshQueued')); }); diff --git a/src/components/remotecontrol/remotecontrol.js b/src/components/remotecontrol/remotecontrol.js index ac9ceaae00..eb897d1fec 100644 --- a/src/components/remotecontrol/remotecontrol.js +++ b/src/components/remotecontrol/remotecontrol.js @@ -1,20 +1,21 @@ -import datetime from 'datetime'; -import backdrop from 'backdrop'; -import listView from 'listView'; -import imageLoader from 'imageLoader'; -import playbackManager from 'playbackManager'; -import nowPlayingHelper from 'nowPlayingHelper'; -import events from 'events'; -import appHost from 'apphost'; -import globalize from 'globalize'; -import layoutManager from 'layoutManager'; -import * as userSettings from 'userSettings'; -import cardBuilder from 'cardBuilder'; -import itemContextMenu from 'itemContextMenu'; -import 'cardStyle'; -import 'emby-itemscontainer'; -import 'css!./remotecontrol.css'; -import 'emby-ratingbutton'; +import datetime from '../../scripts/datetime'; +import backdrop from '../backdrop/backdrop'; +import listView from '../listview/listview'; +import imageLoader from '../images/imageLoader'; +import playbackManager from '../playback/playbackmanager'; +import nowPlayingHelper from '../playback/nowplayinghelper'; +import events from 'jellyfin-apiclient'; +import connectionManager from 'jellyfin-apiclient'; +import appHost from '../apphost'; +import globalize from '../../scripts/globalize'; +import layoutManager from '../layoutManager'; +import * as userSettings from '../../scripts/settings/userSettings'; +import cardBuilder from '../cardbuilder/cardBuilder'; +import itemContextMenu from '../itemContextMenu'; +import '../cardbuilder/card.css'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; +import './remotecontrol.css'; +import '../../elements/emby-ratingbutton/emby-ratingbutton'; /*eslint prefer-const: "error"*/ @@ -37,7 +38,7 @@ function showAudioMenu(context, player, button, item) { return menuItem; }); - import('actionsheet').then(({ default: actionsheet }) => { + import('../actionSheet/actionSheet').then((actionsheet) => { actionsheet.show({ items: menuItems, positionTo: button, @@ -69,7 +70,7 @@ function showSubtitleMenu(context, player, button, item) { selected: currentIndex == null }); - import('actionsheet').then(({ default: actionsheet }) => { + import('../actionSheet/actionSheet').then((actionsheet) => { actionsheet.show({ items: menuItems, positionTo: button, @@ -693,7 +694,7 @@ export default function () { } function savePlaylist() { - import('playlistEditor').then(({ default: playlistEditor }) => { + import('../playlisteditor/playlisteditor').then((playlistEditor) => { getSaveablePlaylistItems().then(function (items) { const serverId = items.length ? items[0].ServerId : ApiClient.serverId(); new playlistEditor({ @@ -863,7 +864,7 @@ export default function () { }, currentPlayer); form.querySelector('input').value = ''; - import('toast').then(({ default: toast }) => { + import('../toast/toast').then((toast) => { toast('Message sent.'); }); @@ -882,7 +883,7 @@ export default function () { }, currentPlayer); form.querySelector('input').value = ''; - import('toast').then(({ default: toast }) => { + import('../toast/toast').then((toast) => { toast('Text sent.'); }); diff --git a/src/components/scrollManager.js b/src/components/scrollManager.js index 549cb9445c..51a718476a 100644 --- a/src/components/scrollManager.js +++ b/src/components/scrollManager.js @@ -5,9 +5,9 @@ * @module components/scrollManager */ -import dom from 'dom'; -import browser from 'browser'; -import layoutManager from 'layoutManager'; +import dom from '../scripts/dom'; +import browser from '../scripts/browser'; +import layoutManager from './layoutManager'; /** * Scroll time in ms. @@ -223,7 +223,7 @@ import layoutManager from 'layoutManager'; let parent = element.parentElement; while (parent) { - // Skip 'emby-scroller' because it scrolls by itself + // Skip '../../elements/emby-scroller/emby-scroller' because it scrolls by itself if (!parent.classList.contains('emby-scroller') && parent[nameScroll] > parent[nameClient] && parent.classList.contains(nameClass)) { return parent; diff --git a/src/components/search/searchfields.js b/src/components/search/searchfields.js index b3cb3cf4c4..3b985c05a9 100644 --- a/src/components/search/searchfields.js +++ b/src/components/search/searchfields.js @@ -1,12 +1,12 @@ -import layoutManager from 'layoutManager'; -import globalize from 'globalize'; -import events from 'events'; -import browser from 'browser'; -import AlphaPicker from 'alphaPicker'; -import 'emby-input'; -import 'flexStyles'; -import 'material-icons'; -import 'css!./searchfields'; +import layoutManager from '../layoutManager'; +import globalize from '../../scripts/globalize'; +import events from 'jellyfin-apiclient'; +import browser from '../../scripts/browser'; +import AlphaPicker from '../alphaPicker/alphaPicker'; +import '../../elements/emby-input/emby-input'; +import '../../assets/css/flexstyles.css'; +import 'material-design-icons-iconfont'; +import './searchfields.css'; /* eslint-disable indent */ @@ -61,7 +61,7 @@ import 'css!./searchfields'; } function embed(elem, instance, options) { - import('text!./searchfields.template.html').then(({default: template}) => { + import('./searchfields.template.html').then(({default: template}) => { let html = globalize.translateHtml(template, 'core'); if (browser.tizen || browser.orsay) { diff --git a/src/components/search/searchresults.js b/src/components/search/searchresults.js index d35868d433..9fe1e7b60d 100644 --- a/src/components/search/searchresults.js +++ b/src/components/search/searchresults.js @@ -1,10 +1,11 @@ -import layoutManager from 'layoutManager'; -import globalize from 'globalize'; -import cardBuilder from 'cardBuilder'; -import appRouter from 'appRouter'; -import 'emby-scroller'; -import 'emby-itemscontainer'; -import 'emby-button'; +import layoutManager from '../layoutManager'; +import globalize from '../../scripts/globalize'; +import connectionManager from 'jellyfin-apiclient'; +import cardBuilder from '../cardbuilder/cardBuilder'; +import appRouter from '../appRouter'; +import '../../elements/emby-scroller/emby-scroller'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; +import '../../elements/emby-button/emby-button'; /* eslint-disable indent */ @@ -584,7 +585,7 @@ import 'emby-button'; } function embed(elem, instance, options) { - import('text!./searchresults.template.html').then(({default: template}) => { + import('./searchresults.template.html').then(({default: template}) => { if (!enableScrollX()) { template = replaceAll(template, 'data-horizontal="true"', 'data-horizontal="false"'); template = replaceAll(template, 'itemsContainer scrollSlider', 'itemsContainer scrollSlider vertical-wrap'); diff --git a/src/components/settingshelper.js b/src/components/settingshelper.js index 3db638c7ad..ca78369ed9 100644 --- a/src/components/settingshelper.js +++ b/src/components/settingshelper.js @@ -1,4 +1,4 @@ -import globalize from 'globalize'; +import globalize from '../scripts/globalize'; /** * Helper for handling settings. diff --git a/src/components/shortcuts.js b/src/components/shortcuts.js index 2959fd3372..2f83a342f2 100644 --- a/src/components/shortcuts.js +++ b/src/components/shortcuts.js @@ -5,12 +5,13 @@ * @module components/shortcuts */ -import playbackManager from 'playbackManager'; -import inputManager from 'inputManager'; -import appRouter from 'appRouter'; -import globalize from 'globalize'; -import dom from 'dom'; -import recordingHelper from 'recordingHelper'; +import playbackManager from './playback/playbackmanager'; +import inputManager from '../scripts/inputManager'; +import connectionManager from 'jellyfin-apiclient'; +import appRouter from './appRouter'; +import globalize from '../scripts/globalize'; +import dom from '../scripts/dom'; +import recordingHelper from './recordingcreator/recordinghelper'; function playAllFromHere(card, serverId, queue) { const parent = card.parentNode; @@ -69,7 +70,8 @@ import recordingHelper from 'recordingHelper'; } function showProgramDialog(item) { - import('recordingCreator').then(({default:recordingCreator}) => { + import('./recordingcreator/recordingcreator' + + '').then(({default:recordingCreator}) => { recordingCreator.show(item.Id, item.ServerId); }); } @@ -109,7 +111,7 @@ import recordingHelper from 'recordingHelper'; item.PlaylistItemId = elem ? elem.getAttribute('data-playlistitemid') : null; } - import('itemContextMenu').then(({default: itemContextMenu}) => { + import('./itemContextMenu').then((itemContextMenu) => { window.connectionManager.getApiClient(item.ServerId).getCurrentUser().then(user => { itemContextMenu.show(Object.assign({ item: item, @@ -153,7 +155,7 @@ import recordingHelper from 'recordingHelper'; function showPlayMenu(card, target) { const item = getItemInfoFromCard(card); - import('playMenu').then(({default: playMenu}) => { + import('./playmenu').then((playMenu) => { playMenu.show({ item: item, @@ -163,7 +165,7 @@ import recordingHelper from 'recordingHelper'; } function sendToast(text) { - import('toast').then(({default: toast}) => { + import('./toast/toast').then((toast) => { toast(text); }); } @@ -269,7 +271,7 @@ import recordingHelper from 'recordingHelper'; } function addToPlaylist(item) { - import('playlistEditor').then(({default: playlistEditor}) => { + import('./playlisteditor/playlisteditor').then((playlistEditor) => { new playlistEditor().show({ items: [item.Id], serverId: item.ServerId @@ -294,16 +296,16 @@ import recordingHelper from 'recordingHelper'; if (item.Type === 'Timer') { if (item.ProgramId) { - import('recordingCreator').then(({default: recordingCreator}) => { + import('./recordingcreator/recordingcreator').then((recordingCreator) => { recordingCreator.show(item.ProgramId, serverId).then(resolve, reject); }); } else { - import('recordingEditor').then(({default: recordingEditor}) => { + import('./recordingcreator/recordingeditor').then((recordingEditor) => { recordingEditor.show(item.Id, serverId).then(resolve, reject); }); } } else { - import('metadataEditor').then(({default: metadataEditor}) => { + import('./metadataEditor/metadataEditor').then((metadataEditor) => { metadataEditor.show(item.Id, serverId).then(resolve, reject); }); } diff --git a/src/components/slideshow/slideshow.js b/src/components/slideshow/slideshow.js index 028c21b221..a33e06b27c 100644 --- a/src/components/slideshow/slideshow.js +++ b/src/components/slideshow/slideshow.js @@ -2,16 +2,17 @@ * Image viewer component * @module components/slideshow/slideshow */ -import dialogHelper from 'dialogHelper'; -import inputManager from 'inputManager'; -import layoutManager from 'layoutManager'; -import focusManager from 'focusManager'; -import browser from 'browser'; -import appHost from 'apphost'; -import dom from 'dom'; -import 'css!./style'; -import 'material-icons'; -import 'paper-icon-button-light'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import inputManager from '../../scripts/inputManager'; +import connectionManager from 'jellyfin-apiclient'; +import layoutManager from '../layoutManager'; +import focusManager from '../focusManager'; +import browser from '../../scripts/browser'; +import appHost from '../apphost'; +import dom from '../../scripts/dom'; +import './style.css'; +import 'material-design-icons-iconfont'; +import '../../elements/emby-button/paper-icon-button-light'; /** * Name of transition event. @@ -431,7 +432,7 @@ export default function (options) { function download() { const imageInfo = getCurrentImageInfo(); - import('fileDownloader').then(({default: fileDownloader}) => { + import('../../scripts/fileDownloader').then((fileDownloader) => { fileDownloader.download([imageInfo]); }); } diff --git a/src/components/sortmenu/sortmenu.js b/src/components/sortmenu/sortmenu.js index d38d98c090..1108448459 100644 --- a/src/components/sortmenu/sortmenu.js +++ b/src/components/sortmenu/sortmenu.js @@ -1,13 +1,13 @@ -import dialogHelper from 'dialogHelper'; -import layoutManager from 'layoutManager'; -import globalize from 'globalize'; -import * as userSettings from 'userSettings'; -import 'emby-select'; -import 'paper-icon-button-light'; -import 'material-icons'; -import 'css!./../formdialog'; -import 'emby-button'; -import 'flexStyles'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import layoutManager from '../layoutManager'; +import globalize from '../../scripts/globalize'; +import * as userSettings from '../../scripts/settings/userSettings'; +import '../../elements/emby-select/emby-select'; +import '../../elements/emby-button/paper-icon-button-light'; +import 'material-design-icons-iconfont'; +import '../formdialog.css'; +import '../../elements/emby-button/emby-button'; +import '../../assets/css/flexstyles.css'; function onSubmit(e) { e.preventDefault(); @@ -22,7 +22,7 @@ function initEditor(context, settings) { } function centerFocus(elem, horiz, on) { - import('scrollHelper').then(({default: scrollHelper}) => { + import('../../scripts/scrollHelper').then((scrollHelper) => { const fn = on ? 'on' : 'off'; scrollHelper.centerFocus[fn](elem, horiz); }); @@ -44,7 +44,7 @@ function saveValues(context, settingsKey) { class SortMenu { show(options) { return new Promise(function (resolve, reject) { - import('text!./sortmenu.template.html').then(({default: template}) => { + import('./sortmenu.template.html').then(({default: template}) => { const dialogOptions = { removeOnClose: true, scrollY: false diff --git a/src/components/subtitleeditor/subtitleeditor.js b/src/components/subtitleeditor/subtitleeditor.js index 8e6fb497d9..6a53b4f54f 100644 --- a/src/components/subtitleeditor/subtitleeditor.js +++ b/src/components/subtitleeditor/subtitleeditor.js @@ -1,19 +1,20 @@ -import appHost from 'apphost'; -import dialogHelper from 'dialogHelper'; -import layoutManager from 'layoutManager'; -import globalize from 'globalize'; -import * as userSettings from 'userSettings'; -import loading from 'loading'; -import focusManager from 'focusManager'; -import dom from 'dom'; -import 'emby-select'; -import 'listViewStyle'; -import 'paper-icon-button-light'; -import 'css!./../formdialog'; -import 'material-icons'; -import 'css!./subtitleeditor'; -import 'emby-button'; -import 'flexStyles'; +import appHost from '../apphost'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import layoutManager from '../layoutManager'; +import globalize from '../../scripts/globalize'; +import * as userSettings from '../../scripts/settings/userSettings'; +import connectionManager from 'jellyfin-apiclient'; +import loading from '../loading/loading'; +import focusManager from '../focusManager'; +import dom from '../../scripts/dom'; +import '../../elements/emby-select/emby-select'; +import '../listview/listview.css'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../formdialog.css'; +import 'material-design-icons-iconfont'; +import './subtitleeditor.css'; +import '../../elements/emby-button/emby-button'; +import '../../assets/css/flexstyles.css'; let currentItem; let hasChanges; @@ -30,7 +31,7 @@ function downloadRemoteSubtitles(context, id) { }).then(function () { hasChanges = true; - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('MessageDownloadQueued')); }); @@ -41,7 +42,7 @@ function downloadRemoteSubtitles(context, id) { function deleteLocalSubtitle(context, index) { const msg = globalize.translate('MessageAreYouSureDeleteSubtitles'); - import('confirm').then(({default: confirm}) => { + import('../confirm/confirm').then((confirm) => { confirm({ title: globalize.translate('ConfirmDeletion'), @@ -329,7 +330,7 @@ function showDownloadOptions(button, context, subtitleId) { id: 'download' }); - import('actionsheet').then(({default: actionsheet}) => { + import('../actionSheet/actionSheet').then((actionsheet) => { actionsheet.show({ items: items, positionTo: button @@ -347,7 +348,7 @@ function showDownloadOptions(button, context, subtitleId) { } function centerFocus(elem, horiz, on) { - import('scrollHelper').then(({default: scrollHelper}) => { + import('../../scripts/scrollHelper').then(({default: scrollHelper}) => { const fn = on ? 'on' : 'off'; scrollHelper.centerFocus[fn](elem, horiz); }); @@ -431,7 +432,7 @@ function showEditor(itemId, serverId) { loading.show(); return new Promise(function (resolve, reject) { - import('text!./subtitleeditor.template.html').then(({default: template}) => { + import('./subtitleeditor.template.html').then(({default: template}) => { showEditorInternal(itemId, serverId, template).then(resolve, reject); }); }); diff --git a/src/components/subtitlesettings/subtitlesettings.js b/src/components/subtitlesettings/subtitlesettings.js index 0e2c4e3661..3462d9542e 100644 --- a/src/components/subtitlesettings/subtitlesettings.js +++ b/src/components/subtitlesettings/subtitlesettings.js @@ -1,20 +1,21 @@ -import globalize from 'globalize'; -import appHost from 'apphost'; -import appSettings from 'appSettings'; -import focusManager from 'focusManager'; -import layoutManager from 'layoutManager'; -import loading from 'loading'; -import subtitleAppearanceHelper from 'subtitleAppearanceHelper'; -import settingsHelper from 'settingsHelper'; -import dom from 'dom'; -import events from 'events'; -import 'listViewStyle'; -import 'emby-select'; -import 'emby-slider'; -import 'emby-input'; -import 'emby-checkbox'; -import 'flexStyles'; -import 'css!./subtitlesettings'; +import globalize from '../../scripts/globalize'; +import appHost from '../apphost'; +import appSettings from '../../scripts/settings/appSettings'; +import focusManager from '../focusManager'; +import layoutManager from '../layoutManager'; +import loading from '../loading/loading'; +import connectionManager from 'jellyfin-apiclient'; +import subtitleAppearanceHelper from './subtitleappearancehelper'; +import settingsHelper from '../settingshelper'; +import dom from '../../scripts/dom'; +import events from 'jellyfin-apiclient'; +import '../listview/listview.css'; +import '../../elements/emby-select/emby-select'; +import '../../elements/emby-slider/emby-slider'; +import '../../elements/emby-input/emby-input'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../assets/css/flexstyles.css'; +import './subtitlesettings.css'; /** * Subtitle settings. @@ -87,7 +88,7 @@ function save(instance, context, userId, userSettings, apiClient, enableSaveConf saveUser(context, user, userSettings, instance.appearanceKey, apiClient).then(function () { loading.hide(); if (enableSaveConfirmation) { - import('toast').then(({default: toast}) => { + import('../toast/toast').then((toast) => { toast(globalize.translate('SettingsSaved')); }); } @@ -158,7 +159,7 @@ function hideSubtitlePreview(persistent) { } function embed(options, self) { - import('text!./subtitlesettings.template.html').then(({default: template}) => { + import('./subtitlesettings.template.html').then(({default: template}) => { options.element.classList.add('subtitlesettings'); options.element.innerHTML = globalize.translateHtml(template, 'core'); diff --git a/src/components/subtitlesync/subtitlesync.js b/src/components/subtitlesync/subtitlesync.js index efb2087a1b..c6d38d2f5c 100644 --- a/src/components/subtitlesync/subtitlesync.js +++ b/src/components/subtitlesync/subtitlesync.js @@ -1,7 +1,8 @@ -import playbackManager from 'playbackManager'; -import layoutManager from 'layoutManager'; -import template from 'text!./subtitlesync.template.html'; -import 'css!./subtitlesync'; + +import playbackManager from '../playback/playbackmanager'; +import layoutManager from '../layoutManager'; +import template from './subtitlesync.template.html'; +import './subtitlesync.css'; let player; let subtitleSyncSlider; diff --git a/src/components/syncPlay/groupSelectionMenu.js b/src/components/syncPlay/groupSelectionMenu.js index b554817b8c..8882548e99 100644 --- a/src/components/syncPlay/groupSelectionMenu.js +++ b/src/components/syncPlay/groupSelectionMenu.js @@ -1,11 +1,12 @@ -import events from 'events'; -import playbackManager from 'playbackManager'; -import syncPlayManager from 'syncPlayManager'; -import loading from 'loading'; -import toast from 'toast'; -import actionsheet from 'actionsheet'; -import globalize from 'globalize'; -import playbackPermissionManager from 'playbackPermissionManager'; +import events from 'jellyfin-apiclient'; +import connectionManager from 'jellyfin-apiclient'; +import playbackManager from '../playback/playbackmanager'; +import syncPlayManager from './syncPlayManager'; +import loading from '../loading/loading'; +import toast from '../toast/toast'; +import actionsheet from '../actionSheet/actionSheet'; +import globalize from '../../scripts/globalize'; +import playbackPermissionManager from './playbackPermissionManager'; /** * Gets active player id. @@ -158,7 +159,7 @@ events.on(syncPlayManager, 'enabled', function (e, enabled) { * Shows a menu to handle SyncPlay groups. * @param {HTMLElement} button - Element where to place the menu. */ -export function show (button) { +export default function show (button) { loading.show(); // TODO: should feature be disabled if playback permission is missing? diff --git a/src/components/syncPlay/syncPlayManager.js b/src/components/syncPlay/syncPlayManager.js index c72d20a111..3a9b6e8891 100644 --- a/src/components/syncPlay/syncPlayManager.js +++ b/src/components/syncPlay/syncPlayManager.js @@ -3,11 +3,12 @@ * @module components/syncPlay/syncPlayManager */ -import events from 'events'; -import playbackManager from 'playbackManager'; -import timeSyncManager from 'timeSyncManager'; -import toast from 'toast'; -import globalize from 'globalize'; +import events from 'jellyfin-apiclient'; +import connectionManager from 'jellyfin-apiclient'; +import playbackManager from '../playback/playbackmanager'; +import timeSyncManager from './timeSyncManager'; +import toast from '../toast/toast'; +import globalize from '../../scripts//globalize'; /** * Waits for an event to be triggered on an object. An optional timeout can specified after which the promise is rejected. diff --git a/src/components/syncPlay/timeSyncManager.js b/src/components/syncPlay/timeSyncManager.js index 6ded631de3..d824b2e1d1 100644 --- a/src/components/syncPlay/timeSyncManager.js +++ b/src/components/syncPlay/timeSyncManager.js @@ -3,7 +3,8 @@ * @module components/syncPlay/timeSyncManager */ -import events from 'events'; +import events from 'jellyfin-apiclient'; +import connectionManager from 'jellyfin-apiclient'; /** * Time estimation diff --git a/src/components/tabbedview/tabbedview.js b/src/components/tabbedview/tabbedview.js index 4e7ccb6529..655ca1ace0 100644 --- a/src/components/tabbedview/tabbedview.js +++ b/src/components/tabbedview/tabbedview.js @@ -1,7 +1,7 @@ -import backdrop from 'backdrop'; -import * as mainTabsManager from 'mainTabsManager'; -import layoutManager from 'layoutManager'; -import 'emby-tabs'; +import backdrop from '../backdrop/backdrop'; +import * as mainTabsManager from '../maintabsmanager'; +import layoutManager from '../layoutManager'; +import '../../elements/emby-tabs/emby-tabs'; function onViewDestroy(e) { const tabControllers = this.tabControllers; diff --git a/src/components/themeMediaPlayer.js b/src/components/themeMediaPlayer.js index 8f288a5348..b1b382e9b0 100644 --- a/src/components/themeMediaPlayer.js +++ b/src/components/themeMediaPlayer.js @@ -1,5 +1,6 @@ -import playbackManager from 'playbackManager'; -import * as userSettings from 'userSettings'; +import playbackManager from './playback/playbackmanager'; +import * as userSettings from '../scripts/settings/userSettings'; +import connectionManager from 'jellyfin-apiclient'; let currentOwnerId; let currentThemeIds = []; diff --git a/src/components/toast/toast.js b/src/components/toast/toast.js index d971880672..a26143ea12 100644 --- a/src/components/toast/toast.js +++ b/src/components/toast/toast.js @@ -1,4 +1,4 @@ -import 'css!./toast'; +import './toast'; function remove(elem) { setTimeout(function () { @@ -21,7 +21,7 @@ export default function (options) { } const elem = document.createElement('div'); - elem.classList.add('toast'); + elem.classList.add('../toast/toast'); elem.innerHTML = options.text; document.body.appendChild(elem); diff --git a/src/components/tunerPicker.js b/src/components/tunerPicker.js index 2e7629a3c5..e2793bf9d6 100644 --- a/src/components/tunerPicker.js +++ b/src/components/tunerPicker.js @@ -1,16 +1,17 @@ -import dialogHelper from 'dialogHelper'; -import dom from 'dom'; -import layoutManager from 'layoutManager'; -import globalize from 'globalize'; -import loading from 'loading'; -import browser from 'browser'; -import focusManager from 'focusManager'; -import scrollHelper from 'scrollHelper'; -import 'material-icons'; -import 'formDialogStyle'; -import 'emby-button'; -import 'emby-itemscontainer'; -import 'cardStyle'; +import dialogHelper from './dialogHelper/dialogHelper'; +import dom from '../scripts/dom'; +import layoutManager from './layoutManager'; +import connectionManager from 'jellyfin-apiclient'; +import globalize from '../scripts/globalize'; +import loading from './loading/loading'; +import browser from '../scripts/browser'; +import focusManager from './focusManager'; +import scrollHelper from '../scripts/scrollHelper'; +import 'material-design-icons-iconfont'; +import './formdialog.css'; +import '../elements/emby-button/emby-button'; +import '../elements/emby-itemscontainer/emby-itemscontainer'; +import './cardbuilder/card.css'; const enableFocusTransform = !browser.slow && !browser.edge; diff --git a/src/components/tvproviders/schedulesdirect.js b/src/components/tvproviders/schedulesdirect.js index de469e1845..b6160f93e0 100644 --- a/src/components/tvproviders/schedulesdirect.js +++ b/src/components/tvproviders/schedulesdirect.js @@ -1,13 +1,13 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import globalize from 'globalize'; -import 'emby-checkbox'; -import 'emby-input'; -import 'listViewStyle'; -import 'paper-icon-button-light'; -import 'emby-select'; -import 'emby-button'; -import 'flexStyles'; +import 'jquery'; +import loading from '../loading/loading'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-input/emby-input'; +import '../listview/listview.css'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-select/emby-select'; +import '../../elements/emby-button/emby-button'; +import '../../assets/css/flexstyles.css'; export default function (page, providerId, options) { function reload() { diff --git a/src/components/tvproviders/xmltv.js b/src/components/tvproviders/xmltv.js index a75b29eeb3..9d23f7710b 100644 --- a/src/components/tvproviders/xmltv.js +++ b/src/components/tvproviders/xmltv.js @@ -1,10 +1,10 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import globalize from 'globalize'; -import 'emby-checkbox'; -import 'emby-input'; -import 'listViewStyle'; -import 'paper-icon-button-light'; +import 'jquery'; +import loading from '../loading/loading'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-input/emby-input'; +import '../listview/listview.css'; +import '../../elements/emby-button/paper-icon-button-light'; export default function (page, providerId, options) { function getListingProvider(config, id) { @@ -143,7 +143,7 @@ export default function (page, providerId, options) { function onSelectPathClick(e) { const page = $(e.target).parents('.xmltvForm')[0]; - import('directorybrowser').then(({default: directoryBrowser}) => { + import('../directorybrowser/directorybrowser').then((directoryBrowser) => { const picker = new directoryBrowser(); picker.show({ includeFiles: true, diff --git a/src/components/upnextdialog/upnextdialog.js b/src/components/upnextdialog/upnextdialog.js index 45ac72b139..9515e2ef36 100644 --- a/src/components/upnextdialog/upnextdialog.js +++ b/src/components/upnextdialog/upnextdialog.js @@ -1,14 +1,15 @@ -import dom from 'dom'; -import playbackManager from 'playbackManager'; -import events from 'events'; -import mediaInfo from 'mediaInfo'; -import layoutManager from 'layoutManager'; -import focusManager from 'focusManager'; -import globalize from 'globalize'; -import itemHelper from 'itemHelper'; -import 'css!./upnextdialog'; -import 'emby-button'; -import 'flexStyles'; +import dom from '../../scripts/dom'; +import playbackManager from '../playback/playbackmanager'; +import connectionManager from 'jellyfin-apiclient'; +import events from 'jellyfin-apiclient'; +import mediaInfo from '../mediainfo/mediainfo'; +import layoutManager from '../layoutManager'; +import focusManager from '../focusManager'; +import globalize from '../../scripts/globalize'; +import itemHelper from '../itemHelper'; +import './upnextdialog.css'; +import '../../elements/emby-button/emby-button'; +import '../../assets/css/flexstyles.css'; /* eslint-disable indent */ diff --git a/src/components/userdatabuttons/userdatabuttons.js b/src/components/userdatabuttons/userdatabuttons.js index 6c0cbb8a29..cd906e3bb2 100644 --- a/src/components/userdatabuttons/userdatabuttons.js +++ b/src/components/userdatabuttons/userdatabuttons.js @@ -1,10 +1,11 @@ -import globalize from 'globalize'; -import dom from 'dom'; -import itemHelper from 'itemHelper'; -import 'paper-icon-button-light'; -import 'material-icons'; -import 'emby-button'; -import 'css!./userdatabuttons'; +import connectionManager from 'jellyfin-apiclient'; +import globalize from '../../scripts/globalize'; +import dom from '../../scripts/dom'; +import itemHelper from '../itemHelper'; +import '../../elements/emby-button/paper-icon-button-light'; +import 'material-design-icons-iconfont'; +import '../../elements/emby-button/emby-button'; +import './userdatabuttons.css'; const userDataMethods = { markPlayed: markPlayed, @@ -19,7 +20,7 @@ function getUserDataButtonHtml(method, itemId, serverId, buttonCssClass, iconCss buttonCssClass = buttonCssClass ? (buttonCssClass + ' mini') : 'mini'; } - const is = style === 'fab' ? 'emby-button' : 'paper-icon-button-light'; + const is = style === 'fab' ? '../../elements/emby-button/emby-button' : '../../elements/emby-button/paper-icon-button-light'; let className = style === 'fab' ? 'autoSize fab' : 'autoSize'; if (buttonCssClass) { @@ -32,7 +33,7 @@ function getUserDataButtonHtml(method, itemId, serverId, buttonCssClass, iconCss iconCssClass = ''; } - iconCssClass += 'material-icons'; + iconCssClass += 'material-design-icons-iconfont'; return ''; } diff --git a/src/components/viewContainer.js b/src/components/viewContainer.js index 6f9059cb10..5672da9c9a 100644 --- a/src/components/viewContainer.js +++ b/src/components/viewContainer.js @@ -1,4 +1,4 @@ -import 'css!components/viewManager/viewContainer'; +import './viewManager/viewContainer.css'; /* eslint-disable indent */ function setControllerClass(view, options) { diff --git a/src/components/viewManager/viewManager.js b/src/components/viewManager/viewManager.js index a4ee22e750..cfcd67cf89 100644 --- a/src/components/viewManager/viewManager.js +++ b/src/components/viewManager/viewManager.js @@ -1,7 +1,7 @@ -import viewContainer from 'viewContainer'; -import focusManager from 'focusManager'; -import queryString from 'queryString'; -import layoutManager from 'layoutManager'; +import viewContainer from '../viewContainer'; +import focusManager from '../focusManager'; +import queryString from 'query-string'; +import layoutManager from '../layoutManager'; let currentView; let dispatchPageEvents; @@ -170,6 +170,6 @@ class ViewManager { } const viewManager = new ViewManager(); -viewManager.default.dispatchPageEvents(true); +viewManager.dispatchPageEvents(true); export default viewManager; diff --git a/src/components/viewSettings/viewSettings.js b/src/components/viewSettings/viewSettings.js index fd5b5c3f9e..2e54f7f223 100644 --- a/src/components/viewSettings/viewSettings.js +++ b/src/components/viewSettings/viewSettings.js @@ -1,15 +1,15 @@ -import dialogHelper from 'dialogHelper'; -import layoutManager from 'layoutManager'; -import globalize from 'globalize'; -import * as userSettings from 'userSettings'; -import 'emby-checkbox'; -import 'emby-input'; -import 'paper-icon-button-light'; -import 'emby-select'; -import 'material-icons'; -import 'css!./../formdialog'; -import 'emby-button'; -import 'flexStyles'; +import dialogHelper from '../dialogHelper/dialogHelper'; +import layoutManager from '../layoutManager'; +import globalize from '../../scripts/globalize'; +import * as userSettings from '../../scripts/settings/userSettings'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-input/emby-input'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-select/emby-select'; +import 'material-design-icons-iconfont'; +import '../formdialog.css'; +import '../../assets/css/flexstyles.css'; function onSubmit(e) { e.preventDefault(); @@ -38,7 +38,7 @@ function saveValues(context, settings, settingsKey) { } function centerFocus(elem, horiz, on) { - import('scrollHelper').then(({default: scrollHelper}) => { + import('../../scripts/scrollHelper').then((scrollHelper) => { const fn = on ? 'on' : 'off'; scrollHelper.centerFocus[fn](elem, horiz); }); @@ -59,7 +59,7 @@ class ViewSettings { } show(options) { return new Promise(function (resolve, reject) { - import('text!./viewSettings.template.html').then(({default: template}) => { + import('./viewSettings.template.html').then(({default: template}) => { const dialogOptions = { removeOnClose: true, scrollY: false diff --git a/src/controllers/dashboard/apikeys.js b/src/controllers/dashboard/apikeys.js index 2b526aa8cc..fccdc189d2 100644 --- a/src/controllers/dashboard/apikeys.js +++ b/src/controllers/dashboard/apikeys.js @@ -1,13 +1,13 @@ -import datetime from 'datetime'; -import loading from 'loading'; -import dom from 'dom'; -import globalize from 'globalize'; -import 'emby-button'; +import datetime from '../../scripts/datetime'; +import loading from '../../components/loading/loading'; +import dom from '../../scripts/dom'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-button/emby-button'; /* eslint-disable indent */ function revoke(page, key) { - import('confirm').then(({default: confirm}) => { + import('../../components/confirm/confirm').then(({default: confirm}) => { confirm(globalize.translate('MessageConfirmRevokeApiKey'), globalize.translate('HeaderConfirmRevokeApiKey')).then(function () { loading.show(); ApiClient.ajax({ @@ -51,7 +51,7 @@ import 'emby-button'; } function showNewKeyPrompt(page) { - import('prompt').then(({default: prompt}) => { + import('../../components/prompt/prompt').then(({default: prompt}) => { prompt({ title: globalize.translate('HeaderNewApiKey'), label: globalize.translate('LabelAppName'), diff --git a/src/controllers/dashboard/dashboard.js b/src/controllers/dashboard/dashboard.js index 855ce3ff03..692cc020b8 100644 --- a/src/controllers/dashboard/dashboard.js +++ b/src/controllers/dashboard/dashboard.js @@ -1,28 +1,28 @@ -import datetime from 'datetime'; -import events from 'events'; -import itemHelper from 'itemHelper'; -import serverNotifications from 'serverNotifications'; -import dom from 'dom'; -import taskButton from 'scripts/taskbutton'; -import globalize from 'globalize'; -import * as datefns from 'date-fns'; -import dfnshelper from 'dfnshelper'; -import loading from 'loading'; -import playMethodHelper from 'playMethodHelper'; -import cardBuilder from 'cardBuilder'; -import imageLoader from 'imageLoader'; -import ActivityLog from 'components/activitylog'; -import imageHelper from 'scripts/imagehelper'; -import indicators from 'indicators'; -import 'listViewStyle'; -import 'emby-button'; -import 'flexStyles'; -import 'emby-itemscontainer'; +import datetime from '../../scripts/datetime'; +import { connectionManager, events } from 'jellyfin-apiclient'; +import itemHelper from '../../components/itemHelper'; +import serverNotifications from '../../scripts/serverNotifications'; +import dom from '../../scripts/dom'; +import globalize from '../../scripts/globalize'; +import { formatDistanceToNow } from 'date-fns'; +import { localeWithSuffix } from '../../scripts/dfnshelper'; +import loading from '../../components/loading/loading'; +import playMethodHelper from '../../components/playback/playmethodhelper'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import imageLoader from '../../components/images/imageLoader'; +import ActivityLog from '../../components/activitylog'; +import imageHelper from '../../scripts/imagehelper'; +import indicators from '../../components/indicators/indicators'; +import '../../components/listview/listview.css'; +import '../../elements/emby-button/emby-button'; +import '../../assets/css/flexstyles.css'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; +import taskButton from '../../scripts/taskbutton'; /* eslint-disable indent */ function showPlaybackInfo(btn, session) { - import('alert').then(({default: alert}) => { + import('../../components/alert').then(({default: alert}) => { let title; const text = []; const displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session); @@ -53,7 +53,7 @@ import 'emby-itemscontainer'; } function showSendMessageForm(btn, session) { - import('prompt').then(({default: prompt}) => { + import('../../components/prompt/prompt').then(({default: prompt}) => { prompt({ title: globalize.translate('HeaderSendMessage'), label: globalize.translate('LabelMessageText'), @@ -70,7 +70,7 @@ import 'emby-itemscontainer'; } function showOptionsMenu(btn, session) { - import('actionsheet').then(({default: actionsheet}) => { + import('../../components/actionSheet/actionSheet').then(({default: actionsheet}) => { const menuItems = []; if (session.ServerId && session.DeviceId !== window.connectionManager.deviceId()) { @@ -473,7 +473,7 @@ import 'emby-itemscontainer'; // how dates are returned by the server when the session is active and show something like 'Active now', instead of past/future sentences if (!nowPlayingItem) { return { - html: globalize.translate('LastSeen', datefns.formatDistanceToNow(Date.parse(session.LastActivityDate), dfnshelper.localeWithSuffix)), + html: globalize.translate('LastSeen', formatDistanceToNow(Date.parse(session.LastActivityDate), localeWithSuffix)), image: imgUrl }; } @@ -720,7 +720,7 @@ import 'emby-itemscontainer'; }); }, restart: function (btn) { - import('confirm').then(({default: confirm}) => { + import('../../components/confirm/confirm').then(({default: confirm}) => { confirm({ title: globalize.translate('Restart'), text: globalize.translate('MessageConfirmRestart'), @@ -735,7 +735,7 @@ import 'emby-itemscontainer'; }); }, shutdown: function (btn) { - import('confirm').then(({default: confirm}) => { + import('../../components/confirm/confirm').then(({default: confirm}) => { confirm({ title: globalize.translate('ButtonShutdown'), text: globalize.translate('MessageConfirmShutdown'), diff --git a/src/controllers/dashboard/devices/device.js b/src/controllers/dashboard/devices/device.js index 17e28b9bdb..ec9932d381 100644 --- a/src/controllers/dashboard/devices/device.js +++ b/src/controllers/dashboard/devices/device.js @@ -1,7 +1,7 @@ -import loading from 'loading'; -import dom from 'dom'; -import 'emby-input'; -import 'emby-button'; +import loading from '../../../components/loading/loading'; +import dom from '../../../scripts/dom'; +import '../../../elements/emby-input/emby-input'; +import '../../../elements/emby-button/emby-button'; /* eslint-disable indent */ diff --git a/src/controllers/dashboard/devices/devices.js b/src/controllers/dashboard/devices/devices.js index c6e7281645..2466b24d72 100644 --- a/src/controllers/dashboard/devices/devices.js +++ b/src/controllers/dashboard/devices/devices.js @@ -1,12 +1,12 @@ -import loading from 'loading'; -import dom from 'dom'; -import globalize from 'globalize'; -import imageHelper from 'scripts/imagehelper'; -import * as datefns from 'date-fns'; -import dfnshelper from 'dfnshelper'; -import 'emby-button'; -import 'emby-itemscontainer'; -import 'cardStyle'; +import loading from '../../../components/loading/loading'; +import dom from '../../../scripts/dom'; +import globalize from '../../../scripts/globalize'; +import imageHelper from '../../../scripts/imagehelper'; +import { formatDistanceToNow } from 'date-fns'; +import { localeWithSuffix } from '../../../scripts/dfnshelper'; +import '../../../elements/emby-button/emby-button'; +import '../../../elements/emby-itemscontainer/emby-itemscontainer'; +import '../../../components/cardbuilder/card.css'; /* eslint-disable indent */ @@ -39,7 +39,7 @@ import 'cardStyle'; function deleteDevice(page, id) { const msg = globalize.translate('DeleteDeviceConfirmation'); - import('confirm').then(({default: confirm}) => { + import('../../../components/confirm/confirm').then(({default: confirm}) => { confirm({ text: msg, title: globalize.translate('HeaderDeleteDevice'), @@ -72,7 +72,7 @@ import 'cardStyle'; }); } - import('actionsheet').then(({default: actionsheet}) => { + import('../../../components/actionSheet/actionSheet').then(({default: actionsheet}) => { actionsheet.show({ items: menuItems, positionTo: btn, @@ -118,7 +118,8 @@ import 'cardStyle'; deviceHtml += ''; } - deviceHtml += "
"; + deviceHtml += "
"; deviceHtml += device.Name; deviceHtml += '
'; deviceHtml += "
"; @@ -128,7 +129,7 @@ import 'cardStyle'; if (device.LastUserName) { deviceHtml += device.LastUserName; - deviceHtml += ', ' + datefns.formatDistanceToNow(Date.parse(device.DateLastActivity), dfnshelper.localeWithSuffix); + deviceHtml += ', ' + formatDistanceToNow(Date.parse(device.DateLastActivity), localeWithSuffix); } deviceHtml += ' '; diff --git a/src/controllers/dashboard/dlna/profile.js b/src/controllers/dashboard/dlna/profile.js index 478b5ca878..2a770bf91c 100644 --- a/src/controllers/dashboard/dlna/profile.js +++ b/src/controllers/dashboard/dlna/profile.js @@ -1,11 +1,11 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import globalize from 'globalize'; -import 'emby-select'; -import 'emby-button'; -import 'emby-input'; -import 'emby-checkbox'; -import 'listViewStyle'; +import 'jquery'; +import loading from '../../../components/loading/loading'; +import globalize from '../../../scripts/globalize'; +import '../../../elements/emby-select/emby-select'; +import '../../../elements/emby-button/emby-button'; +import '../../../elements/emby-input/emby-input'; +import '../../../elements/emby-checkbox/emby-checkbox'; +import '../../../components/listview/listview.css'; /* eslint-disable indent */ @@ -633,7 +633,7 @@ import 'listViewStyle'; data: JSON.stringify(profile), contentType: 'application/json' }).then(function () { - import('toast').then(({default: toast}) => { + import('../../../components/toast/toast').then((toast) => { toast('Settings saved.'); }); }, Dashboard.processErrorResponse); diff --git a/src/controllers/dashboard/dlna/profiles.js b/src/controllers/dashboard/dlna/profiles.js index 4eb830df6f..6d3616864f 100644 --- a/src/controllers/dashboard/dlna/profiles.js +++ b/src/controllers/dashboard/dlna/profiles.js @@ -1,9 +1,9 @@ -import $ from 'jQuery'; -import globalize from 'globalize'; -import loading from 'loading'; -import libraryMenu from 'libraryMenu'; -import 'listViewStyle'; -import 'emby-button'; +import 'jquery'; +import globalize from '../../../scripts/globalize'; +import loading from '../../../components/loading/loading'; +import libraryMenu from '../../../scripts/libraryMenu'; +import '../../../components/listview/listview.css'; +import '../../../elements/emby-button/emby-button'; /* eslint-disable indent */ @@ -64,7 +64,7 @@ import 'emby-button'; } function deleteProfile(page, id) { - import('confirm').then(({default: confirm}) => { + import('../../../components/confirm/confirm').then(({default: confirm}) => { confirm(globalize.translate('MessageConfirmProfileDeletion'), globalize.translate('HeaderConfirmProfileDeletion')).then(function () { loading.show(); ApiClient.ajax({ diff --git a/src/controllers/dashboard/dlna/settings.js b/src/controllers/dashboard/dlna/settings.js index fb93441a55..f5591cdef8 100644 --- a/src/controllers/dashboard/dlna/settings.js +++ b/src/controllers/dashboard/dlna/settings.js @@ -1,7 +1,7 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import libraryMenu from 'libraryMenu'; -import globalize from 'globalize'; +import 'jquery'; +import loading from '../../../components/loading/loading'; +import libraryMenu from '../../../scripts/libraryMenu'; +import globalize from '../../../scripts/globalize'; /* eslint-disable indent */ diff --git a/src/controllers/dashboard/encodingsettings.js b/src/controllers/dashboard/encodingsettings.js index 6a54e8105d..7bd611df6c 100644 --- a/src/controllers/dashboard/encodingsettings.js +++ b/src/controllers/dashboard/encodingsettings.js @@ -1,8 +1,8 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import globalize from 'globalize'; -import dom from 'dom'; -import libraryMenu from 'libraryMenu'; +import 'jquery'; +import loading from '../../components/loading/loading'; +import globalize from '../../scripts/globalize'; +import dom from '../../scripts/dom'; +import libraryMenu from '../../scripts/libraryMenu'; /* eslint-disable indent */ @@ -45,7 +45,7 @@ import libraryMenu from 'libraryMenu'; let msg = ''; msg = globalize.translate('FFmpegSavePathNotFound'); - import('alert').then(({default: alert}) => { + import('../../components/alert').then(({default: alert}) => { alert(msg); }); } @@ -101,7 +101,7 @@ import libraryMenu from 'libraryMenu'; ApiClient.updateNamedConfiguration('encoding', config).then(function () { updateEncoder(form); }, function () { - import('alert').then(({default: alert}) => { + import('../../components/alert').then(({default: alert}) => { alert(globalize.translate('ErrorDefault')); }); @@ -111,7 +111,7 @@ import libraryMenu from 'libraryMenu'; }; if ($('#selectVideoDecoder', form).val()) { - import('alert').then(({default: alert}) => { + import('../../components/alert').then(({default: alert}) => { alert({ title: globalize.translate('TitleHardwareAcceleration'), text: globalize.translate('HardwareAccelerationWarning') @@ -186,7 +186,7 @@ import libraryMenu from 'libraryMenu'; setDecodingCodecsVisible(page, this.value); }); $('#btnSelectEncoderPath', page).on('click.selectDirectory', function () { - import('directorybrowser').then(({default: directoryBrowser}) => { + import('../../components/directorybrowser/directorybrowser').then(({default: directoryBrowser}) => { const picker = new directoryBrowser(); picker.show({ includeFiles: true, @@ -201,7 +201,7 @@ import libraryMenu from 'libraryMenu'; }); }); $('#btnSelectTranscodingTempPath', page).on('click.selectDirectory', function () { - import('directorybrowser').then(({default: directoryBrowser}) => { + import('../../components/directorybrowser/directorybrowser').then(({default: directoryBrowser}) => { const picker = new directoryBrowser(); picker.show({ callback: function (path) { diff --git a/src/controllers/dashboard/general.js b/src/controllers/dashboard/general.js index eb819dc415..fb7b1c59d5 100644 --- a/src/controllers/dashboard/general.js +++ b/src/controllers/dashboard/general.js @@ -1,11 +1,11 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import globalize from 'globalize'; -import 'emby-checkbox'; -import 'emby-textarea'; -import 'emby-input'; -import 'emby-select'; -import 'emby-button'; +import 'jquery'; +import loading from '../../components/loading/loading'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-textarea/emby-textarea'; +import '../../elements/emby-input/emby-input'; +import '../../elements/emby-select/emby-select'; +import '../../elements/emby-button/emby-button'; /* eslint-disable indent */ @@ -51,7 +51,7 @@ import 'emby-button'; }); }); }, function () { - import('alert').then(({default: alert}) => { + import('../../components/alert').then(({default: alert}) => { alert(globalize.translate('ErrorDefault')); }); @@ -66,7 +66,7 @@ import 'emby-button'; const brandingConfigKey = 'branding'; export default function (view, params) { $('#btnSelectCachePath', view).on('click.selectDirectory', function () { - import('directorybrowser').then(({default: directoryBrowser}) => { + import('../../components/directorybrowser/directorybrowser').then(({default: directoryBrowser}) => { const picker = new directoryBrowser(); picker.show({ callback: function (path) { @@ -83,7 +83,7 @@ import 'emby-button'; }); }); $('#btnSelectMetadataPath', view).on('click.selectDirectory', function () { - import('directorybrowser').then(({default: directoryBrowser}) => { + import('../../components/directorybrowser/directorybrowser').then(({default: directoryBrowser}) => { const picker = new directoryBrowser(); picker.show({ path: $('#txtMetadataPath', view).val(), diff --git a/src/controllers/dashboard/library.js b/src/controllers/dashboard/library.js index 0abda33b6e..9ef5f77fa3 100644 --- a/src/controllers/dashboard/library.js +++ b/src/controllers/dashboard/library.js @@ -1,17 +1,17 @@ -import $ from 'jQuery'; -import taskButton from 'scripts/taskbutton'; -import loading from 'loading'; -import libraryMenu from 'libraryMenu'; -import globalize from 'globalize'; -import dom from 'dom'; -import imageHelper from 'scripts/imagehelper'; -import 'cardStyle'; -import 'emby-itemrefreshindicator'; +import 'jquery'; +import taskButton from '../../scripts/taskbutton'; +import loading from '../../components/loading/loading'; +import libraryMenu from '../../scripts/libraryMenu'; +import globalize from '../../scripts/globalize'; +import dom from '../../scripts/dom'; +import imageHelper from '../../scripts/imagehelper'; +import '../../components/cardbuilder/card.css'; +import '../../elements/emby-itemrefreshindicator/emby-itemrefreshindicator'; /* eslint-disable indent */ function addVirtualFolder(page) { - import('medialibrarycreator').then(({default: medialibrarycreator}) => { + import('../../components/mediaLibraryCreator/mediaLibraryCreator').then((medialibrarycreator) => { new medialibrarycreator({ collectionTypeOptions: getCollectionTypeOptions().filter(function (f) { return !f.hidden; @@ -26,7 +26,7 @@ import 'emby-itemrefreshindicator'; } function editVirtualFolder(page, virtualFolder) { - import('medialibraryeditor').then(({default: medialibraryeditor}) => { + import('../../components/mediaLibraryEditor/mediaLibraryEditor').then((medialibraryeditor) => { new medialibraryeditor({ refresh: shouldRefreshLibraryAfterChanges(page), library: virtualFolder @@ -46,7 +46,7 @@ import 'emby-itemrefreshindicator'; msg += virtualFolder.Locations.join('
'); } - import('confirm').then(({default: confirm}) => { + import('../../components/confirm/confirm').then((confirm) => { confirm({ text: msg, title: globalize.translate('HeaderRemoveMediaFolder'), @@ -62,7 +62,7 @@ import 'emby-itemrefreshindicator'; } function refreshVirtualFolder(page, virtualFolder) { - import('refreshDialog').then(({default: refreshDialog}) => { + import('../../components/refreshdialog/refreshdialog').then((refreshDialog) => { new refreshDialog({ itemIds: [virtualFolder.ItemId], serverId: ApiClient.serverId(), @@ -72,7 +72,7 @@ import 'emby-itemrefreshindicator'; } function renameVirtualFolder(page, virtualFolder) { - import('prompt').then(({default: prompt}) => { + import('../../components/prompt/prompt').then((prompt) => { prompt({ label: globalize.translate('LabelNewName'), confirmText: globalize.translate('ButtonRename') @@ -118,7 +118,7 @@ import 'emby-itemrefreshindicator'; icon: 'refresh' }); - import('actionsheet').then(({default: actionsheet}) => { + import('../../components/actionSheet/actionSheet').then((actionsheet) => { actionsheet.show({ items: menuItems, positionTo: elem, @@ -199,7 +199,7 @@ import 'emby-itemrefreshindicator'; } function editImages(page, virtualFolder) { - import('imageEditor').then(({default: imageEditor}) => { + import('../../components/imageeditor/imageeditor').then((imageEditor) => { imageEditor.show({ itemId: virtualFolder.ItemId, serverId: ApiClient.serverId() diff --git a/src/controllers/dashboard/librarydisplay.js b/src/controllers/dashboard/librarydisplay.js index 06e366b988..fbae27fe75 100644 --- a/src/controllers/dashboard/librarydisplay.js +++ b/src/controllers/dashboard/librarydisplay.js @@ -1,8 +1,8 @@ -import globalize from 'globalize'; -import loading from 'loading'; -import libraryMenu from 'libraryMenu'; -import 'emby-checkbox'; -import 'emby-button'; +import globalize from '../../scripts/globalize'; +import loading from '../../components/loading/loading'; +import libraryMenu from '../../scripts/libraryMenu'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-button/emby-button'; /* eslint-disable indent */ diff --git a/src/controllers/dashboard/logs.js b/src/controllers/dashboard/logs.js index e28c2ac12f..68431441c2 100644 --- a/src/controllers/dashboard/logs.js +++ b/src/controllers/dashboard/logs.js @@ -1,8 +1,8 @@ -import datetime from 'datetime'; -import loading from 'loading'; -import 'emby-button'; -import 'listViewStyle'; -import 'flexStyles'; +import datetime from '../../scripts/datetime'; +import loading from '../../components/loading/loading'; +import '../../elements/emby-button/emby-button'; +import '../../components/listview/listview.css'; +import '../../assets/css/flexstyles.css'; /* eslint-disable indent */ diff --git a/src/controllers/dashboard/metadataImages.js b/src/controllers/dashboard/metadataImages.js index 649ca9ac31..afc19c0edf 100644 --- a/src/controllers/dashboard/metadataImages.js +++ b/src/controllers/dashboard/metadataImages.js @@ -1,8 +1,8 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import libraryMenu from 'libraryMenu'; -import globalize from 'globalize'; -import 'listViewStyle'; +import 'jquery'; +import loading from '../../components/loading/loading'; +import libraryMenu from '../../scripts/libraryMenu'; +import globalize from '../../scripts/globalize'; +import '../../components/listview/listview.css'; /* eslint-disable indent */ diff --git a/src/controllers/dashboard/metadatanfo.js b/src/controllers/dashboard/metadatanfo.js index 16e1018e44..e3fd0df002 100644 --- a/src/controllers/dashboard/metadatanfo.js +++ b/src/controllers/dashboard/metadatanfo.js @@ -1,7 +1,7 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import libraryMenu from 'libraryMenu'; -import globalize from 'globalize'; +import 'jquery'; +import loading from '../../components/loading/loading'; +import libraryMenu from '../../scripts/libraryMenu'; +import globalize from '../../scripts/globalize'; /* eslint-disable indent */ @@ -39,7 +39,7 @@ import globalize from 'globalize'; const msg = []; msg.push(globalize.translate('MetadataSettingChangeHelp')); - import('alert').then(({default: alert}) => { + import('../../components/alert').then(({default: alert}) => { alert({ text: msg.join('

') }); diff --git a/src/controllers/dashboard/networking.js b/src/controllers/dashboard/networking.js index 7fc161a90b..a68a334878 100644 --- a/src/controllers/dashboard/networking.js +++ b/src/controllers/dashboard/networking.js @@ -1,7 +1,7 @@ -import loading from 'loading'; -import globalize from 'globalize'; -import 'emby-checkbox'; -import 'emby-select'; +import loading from '../../components/loading/loading'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-select/emby-select'; /* eslint-disable indent */ @@ -89,7 +89,7 @@ import 'emby-select'; function showAlertText(options) { return new Promise(function (resolve, reject) { - import('alert').then(({default: alert}) => { + import('../../components/alert').then(({default: alert}) => { alert(options).then(resolve, reject); }); }); @@ -145,7 +145,7 @@ import 'emby-select'; } }); view.querySelector('#btnSelectCertPath').addEventListener('click', function () { - import('directorybrowser').then(({default: directoryBrowser}) => { + import('../../components/directorybrowser/directorybrowser').then(({default: directoryBrowser}) => { const picker = new directoryBrowser(); picker.show({ includeFiles: true, diff --git a/src/controllers/dashboard/notifications/notification/index.js b/src/controllers/dashboard/notifications/notification/index.js index 2ab3720ccb..1501a9a7b5 100644 --- a/src/controllers/dashboard/notifications/notification/index.js +++ b/src/controllers/dashboard/notifications/notification/index.js @@ -1,5 +1,5 @@ -import $ from 'jQuery'; -import 'emby-checkbox'; +import 'jquery'; +import '../../../../elements/emby-checkbox/emby-checkbox'; function fillItems(elem, items, cssClass, idPrefix, currentList, isEnabledList) { let html = '
'; diff --git a/src/controllers/dashboard/notifications/notifications/index.js b/src/controllers/dashboard/notifications/notifications/index.js index b97403f8eb..1e0575df88 100644 --- a/src/controllers/dashboard/notifications/notifications/index.js +++ b/src/controllers/dashboard/notifications/notifications/index.js @@ -1,7 +1,7 @@ -import loading from 'loading'; -import globalize from 'globalize'; -import 'listViewStyle'; -import 'emby-button'; +import loading from '../../../../components/loading/loading'; +import globalize from '../../../../scripts/globalize'; +import '../../../../components/listview/listview.css'; +import '../../../../elements/emby-button/emby-button'; function reload(page) { loading.show(); diff --git a/src/controllers/dashboard/playback.js b/src/controllers/dashboard/playback.js index 101c3ac0a2..0ea7dc3207 100644 --- a/src/controllers/dashboard/playback.js +++ b/src/controllers/dashboard/playback.js @@ -1,7 +1,7 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import libraryMenu from 'libraryMenu'; -import globalize from 'globalize'; +import 'jquery'; +import loading from '../../components/loading/loading'; +import libraryMenu from '../../scripts/libraryMenu'; +import globalize from '../../scripts/globalize'; /* eslint-disable indent */ diff --git a/src/controllers/dashboard/plugins/add/index.js b/src/controllers/dashboard/plugins/add/index.js index 5cc1dd3215..3854087e7e 100644 --- a/src/controllers/dashboard/plugins/add/index.js +++ b/src/controllers/dashboard/plugins/add/index.js @@ -1,7 +1,7 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import globalize from 'globalize'; -import 'emby-button'; +import 'jquery'; +import loading from '../../../../components/loading/loading'; +import globalize from '../../../../scripts/globalize'; +import '../../../../elements/emby-button/emby-button'; function populateHistory(packageInfo, page) { let html = ''; @@ -68,7 +68,7 @@ function renderPackage(pkg, installedPlugins, page) { } function alertText(options) { - import('alert').then(({default: alert}) => { + import('../../../../components/alert').then(({default: alert}) => { alert(options); }); } @@ -94,7 +94,7 @@ function performInstallation(page, name, guid, version) { msg += '
'; msg += globalize.translate('PleaseConfirmPluginInstallation'); - import('confirm').then(({default: confirm}) => { + import('../../../../components/confirm/confirm').then(({default: confirm}) => { confirm(msg, globalize.translate('HeaderConfirmPluginInstallation')).then(function () { alertCallback(); }).catch(() => { diff --git a/src/controllers/dashboard/plugins/available/index.js b/src/controllers/dashboard/plugins/available/index.js index b7c3505aa1..7dc4a9e42d 100644 --- a/src/controllers/dashboard/plugins/available/index.js +++ b/src/controllers/dashboard/plugins/available/index.js @@ -1,10 +1,10 @@ -import loading from 'loading'; -import libraryMenu from 'libraryMenu'; -import globalize from 'globalize'; -import 'cardStyle'; -import 'emby-button'; -import 'emby-checkbox'; -import 'emby-select'; +import loading from '../../../../components/loading/loading'; +import libraryMenu from '../../../../scripts/libraryMenu'; +import globalize from '../../../../scripts/globalize'; +import '../../../../components/cardbuilder/card.css'; +import '../../../../elements/emby-button/emby-button'; +import '../../../../elements/emby-checkbox/emby-checkbox'; +import '../../../../elements/emby-select/emby-select'; function reloadList(page) { loading.show(); diff --git a/src/controllers/dashboard/plugins/installed/index.js b/src/controllers/dashboard/plugins/installed/index.js index cdf21d6a3c..26e98a3277 100644 --- a/src/controllers/dashboard/plugins/installed/index.js +++ b/src/controllers/dashboard/plugins/installed/index.js @@ -1,14 +1,14 @@ -import loading from 'loading'; -import libraryMenu from 'libraryMenu'; -import dom from 'dom'; -import globalize from 'globalize'; -import 'cardStyle'; -import 'emby-button'; +import loading from '../../../../components/loading/loading'; +import libraryMenu from '../../../../scripts/libraryMenu'; +import dom from '../../../../scripts/dom'; +import globalize from '../../../../scripts/globalize'; +import '../../../../components/cardbuilder/card.css'; +import '../../../../elements/emby-button/emby-button'; function deletePlugin(page, uniqueid, name) { const msg = globalize.translate('UninstallPluginConfirmation', name); - import('confirm').then(({default: confirm}) => { + import('../../../../components/confirm/confirm').then((confirm) => { confirm.default({ title: globalize.translate('HeaderUninstallPlugin'), text: msg, @@ -132,7 +132,7 @@ function showPluginMenu(page, elem) { }); } - import('actionsheet').then(({default: actionsheet}) => { + import('../../../../components/actionSheet/actionSheet').then((actionsheet) => { actionsheet.show({ items: menuItems, positionTo: elem, diff --git a/src/controllers/dashboard/plugins/repositories/index.js b/src/controllers/dashboard/plugins/repositories/index.js index 3abee6c90f..08a411545c 100644 --- a/src/controllers/dashboard/plugins/repositories/index.js +++ b/src/controllers/dashboard/plugins/repositories/index.js @@ -1,12 +1,12 @@ -import loading from 'loading'; -import libraryMenu from 'libraryMenu'; -import globalize from 'globalize'; -import dialogHelper from 'dialogHelper'; -import 'emby-button'; -import 'emby-checkbox'; -import 'emby-select'; -import 'formDialogStyle'; -import 'listViewStyle'; +import loading from '../../../../components/loading/loading'; +import libraryMenu from '../../../../scripts/libraryMenu'; +import globalize from '../../../../scripts/globalize'; +import dialogHelper from '../../../../components/dialogHelper/dialogHelper'; +import '../../../../elements/emby-button/emby-button'; +import '../../../../elements/emby-checkbox/emby-checkbox'; +import '../../../../elements/emby-select/emby-select'; +import '../../../../components/formdialog.css'; +import '../../../../components/listview/listview.css'; let repositories = []; diff --git a/src/controllers/dashboard/scheduledtasks/scheduledtask.js b/src/controllers/dashboard/scheduledtasks/scheduledtask.js index 64c09c6d81..fe131767e6 100644 --- a/src/controllers/dashboard/scheduledtasks/scheduledtask.js +++ b/src/controllers/dashboard/scheduledtasks/scheduledtask.js @@ -1,11 +1,11 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import datetime from 'datetime'; -import dom from 'dom'; -import globalize from 'globalize'; -import 'emby-input'; -import 'emby-button'; -import 'emby-select'; +import 'jquery'; +import loading from '../../../components/loading/loading'; +import datetime from '../../../scripts/datetime'; +import dom from '../../../scripts/dom'; +import globalize from '../../../scripts/globalize'; +import '../../../elements/emby-input/emby-input'; +import '../../../elements/emby-button/emby-button'; +import '../../../elements/emby-select/emby-select'; /* eslint-disable indent */ @@ -42,7 +42,7 @@ import 'emby-select'; $('.taskName', view).html(task.Name); $('#pTaskDescription', view).html(task.Description); - import('listViewStyle').then(() => { + import('../../../components/listview/listview.css').then(() => { ScheduledTaskPage.loadTaskTriggers(view, task); }); @@ -135,7 +135,7 @@ import 'emby-select'; $('#popupAddTrigger', view).removeClass('hide'); }, confirmDeleteTrigger: function (view, index) { - import('confirm').then(({default: confirm}) => { + import('../../../components/confirm/confirm').then(({default: confirm}) => { confirm(globalize.translate('MessageDeleteTaskTrigger'), globalize.translate('HeaderDeleteTaskTrigger')).then(function () { ScheduledTaskPage.deleteTrigger(view, index); }); diff --git a/src/controllers/dashboard/scheduledtasks/scheduledtasks.js b/src/controllers/dashboard/scheduledtasks/scheduledtasks.js index 81a34d4fa6..436a06b746 100644 --- a/src/controllers/dashboard/scheduledtasks/scheduledtasks.js +++ b/src/controllers/dashboard/scheduledtasks/scheduledtasks.js @@ -1,12 +1,12 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import events from 'events'; -import globalize from 'globalize'; -import serverNotifications from 'serverNotifications'; -import * as datefns from 'date-fns'; -import dfnshelper from 'dfnshelper'; -import 'listViewStyle'; -import 'emby-button'; +import 'jquery'; +import loading from '../../../components/loading/loading'; +import events from 'jellyfin-apiclient'; +import globalize from '../../../scripts/globalize'; +import serverNotifications from '../../../scripts/serverNotifications'; +import { formatDistance, formatDistanceToNow } from 'date-fns'; +import { getLocale, localeWithSuffix } from '../../../scripts/dfnshelper'; +import '../../../components/listview/listview.css'; +import '../../../elements/emby-button/emby-button'; /* eslint-disable indent */ @@ -77,8 +77,8 @@ import 'emby-button'; if (task.LastExecutionResult) { const endtime = Date.parse(task.LastExecutionResult.EndTimeUtc); const starttime = Date.parse(task.LastExecutionResult.StartTimeUtc); - html += globalize.translate('LabelScheduledTaskLastRan', datefns.formatDistanceToNow(endtime, dfnshelper.localeWithSuffix), - datefns.formatDistance(starttime, endtime, { locale: dfnshelper.getLocale() })); + html += globalize.translate('LabelScheduledTaskLastRan', formatDistanceToNow(endtime, localeWithSuffix), + formatDistance(starttime, endtime, { locale: getLocale() })); if (task.LastExecutionResult.Status === 'Failed') { html += " (" + globalize.translate('LabelFailed') + ')'; } else if (task.LastExecutionResult.Status === 'Cancelled') { diff --git a/src/controllers/dashboard/serveractivity.js b/src/controllers/dashboard/serveractivity.js index ed56126267..1f44b9eefb 100644 --- a/src/controllers/dashboard/serveractivity.js +++ b/src/controllers/dashboard/serveractivity.js @@ -1,5 +1,5 @@ -import ActivityLog from 'components/activitylog'; -import globalize from 'globalize'; +import ActivityLog from '../../components/activitylog'; +import globalize from '../../scripts/globalize'; /* eslint-disable indent */ diff --git a/src/controllers/dashboard/streaming.js b/src/controllers/dashboard/streaming.js index 5db888dfc1..5fbf67491c 100644 --- a/src/controllers/dashboard/streaming.js +++ b/src/controllers/dashboard/streaming.js @@ -1,7 +1,7 @@ -import $ from 'jQuery'; -import libraryMenu from 'libraryMenu'; -import loading from 'loading'; -import globalize from 'globalize'; +import 'jquery'; +import libraryMenu from '../../scripts/libraryMenu'; +import loading from '../../components/loading/loading'; +import globalize from '../../scripts/globalize'; /* eslint-disable indent */ diff --git a/src/controllers/dashboard/users/useredit.js b/src/controllers/dashboard/users/useredit.js index 3d6e7d8bd9..3532f82621 100644 --- a/src/controllers/dashboard/users/useredit.js +++ b/src/controllers/dashboard/users/useredit.js @@ -1,7 +1,7 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import libraryMenu from 'libraryMenu'; -import globalize from 'globalize'; +import 'jquery'; +import loading from '../../../components/loading/loading'; +import libraryMenu from '../../../scripts/libraryMenu'; +import globalize from '../../../scripts/globalize'; /* eslint-disable indent */ @@ -110,7 +110,7 @@ import globalize from 'globalize'; Dashboard.navigate('userprofiles.html'); loading.hide(); - import('toast').then(({default: toast}) => { + import('../../../components/toast/toast').then((toast) => { toast(globalize.translate('SettingsSaved')); }); } diff --git a/src/controllers/dashboard/users/userlibraryaccess.js b/src/controllers/dashboard/users/userlibraryaccess.js index d840092c45..d07cc8f573 100644 --- a/src/controllers/dashboard/users/userlibraryaccess.js +++ b/src/controllers/dashboard/users/userlibraryaccess.js @@ -1,7 +1,7 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import libraryMenu from 'libraryMenu'; -import globalize from 'globalize'; +import 'jquery'; +import loading from '../../../components/loading/loading'; +import libraryMenu from '../../../scripts/libraryMenu'; +import globalize from '../../../scripts/globalize'; /* eslint-disable indent */ @@ -92,7 +92,7 @@ import globalize from 'globalize'; function onSaveComplete(page) { loading.hide(); - import('toast').then(({default: toast}) => { + import('../../../components/toast/toast').then((toast) => { toast(globalize.translate('SettingsSaved')); }); } diff --git a/src/controllers/dashboard/users/usernew.js b/src/controllers/dashboard/users/usernew.js index 68b6365c02..9e6ffc3fc9 100644 --- a/src/controllers/dashboard/users/usernew.js +++ b/src/controllers/dashboard/users/usernew.js @@ -1,7 +1,7 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import globalize from 'globalize'; -import 'emby-checkbox'; +import 'jquery'; +import loading from '../../../components/loading/loading'; +import globalize from '../../../scripts/globalize'; +import '../../../elements/emby-checkbox/emby-checkbox'; /* eslint-disable indent */ @@ -88,7 +88,7 @@ import 'emby-checkbox'; Dashboard.navigate('useredit.html?userId=' + user.Id); }); }, function (response) { - import('toast').then(({default: toast}) => { + import('../../../components/toast/toast').then((toast) => { toast(globalize.translate('ErrorDefault')); }); diff --git a/src/controllers/dashboard/users/userparentalcontrol.js b/src/controllers/dashboard/users/userparentalcontrol.js index efe00aec0b..8a23a5c414 100644 --- a/src/controllers/dashboard/users/userparentalcontrol.js +++ b/src/controllers/dashboard/users/userparentalcontrol.js @@ -1,10 +1,10 @@ -import $ from 'jQuery'; -import datetime from 'datetime'; -import loading from 'loading'; -import libraryMenu from 'libraryMenu'; -import globalize from 'globalize'; -import 'listViewStyle'; -import 'paper-icon-button-light'; +import 'jquery'; +import datetime from '../../../scripts/datetime'; +import loading from '../../../components/loading/loading'; +import libraryMenu from '../../../scripts/libraryMenu'; +import globalize from '../../../scripts/globalize'; +import '../../../components/listview/listview.css'; +import '../../../elements/emby-button/paper-icon-button-light'; /* eslint-disable indent */ @@ -163,7 +163,7 @@ import 'paper-icon-button-light'; function onSaveComplete(page) { loading.hide(); - import('toast').then(({default: toast}) => { + import('../../../components/toast/toast').then((toast) => { toast(globalize.translate('SettingsSaved')); }); } @@ -195,7 +195,7 @@ import 'paper-icon-button-light'; function showSchedulePopup(page, schedule, index) { schedule = schedule || {}; - import('components/accessSchedule/accessSchedule').then(({default: accessschedule}) => { + import('../../../components/accessSchedule/accessSchedule').then(({default: accessschedule}) => { accessschedule.show({ schedule: schedule }).then(function (updatedSchedule) { @@ -228,7 +228,7 @@ import 'paper-icon-button-light'; } function showBlockedTagPopup(page) { - import('prompt').then(({default: prompt}) => { + import('../../../components/prompt/prompt').then(({default: prompt}) => { prompt({ label: globalize.translate('LabelTag') }).then(function (value) { diff --git a/src/controllers/dashboard/users/userpasswordpage.js b/src/controllers/dashboard/users/userpasswordpage.js index 880dccf9ff..2f5246c54b 100644 --- a/src/controllers/dashboard/users/userpasswordpage.js +++ b/src/controllers/dashboard/users/userpasswordpage.js @@ -1,7 +1,7 @@ -import loading from 'loading'; -import libraryMenu from 'libraryMenu'; -import globalize from 'globalize'; -import 'emby-button'; +import loading from '../../../components/loading/loading'; +import libraryMenu from '../../../scripts/libraryMenu'; +import globalize from '../../../scripts/globalize'; +import '../../../elements/emby-button/emby-button'; /* eslint-disable indent */ @@ -52,7 +52,7 @@ import 'emby-button'; page.querySelector('.chkEnableLocalEasyPassword').checked = user.Configuration.EnableLocalPassword; - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(page); }); }); @@ -82,7 +82,7 @@ import 'emby-button'; ApiClient.updateUserConfiguration(user.Id, user.Configuration).then(function () { loading.hide(); - import('toast').then(({default: toast}) => { + import('../../../components/toast/toast').then((toast) => { toast(globalize.translate('SettingsSaved')); }); @@ -105,7 +105,7 @@ import 'emby-button'; ApiClient.updateUserPassword(userId, currentPassword, newPassword).then(function () { loading.hide(); - import('toast').then(({default: toast}) => { + import('../../../components/toast/toast').then((toast) => { toast(globalize.translate('PasswordSaved')); }); @@ -123,7 +123,7 @@ import 'emby-button'; const form = this; if (form.querySelector('#txtNewPassword').value != form.querySelector('#txtNewPasswordConfirm').value) { - import('toast').then(({default: toast}) => { + import('../../../components/toast/toast').then((toast) => { toast(globalize.translate('PasswordMatchError')); }); } else { @@ -144,7 +144,7 @@ import 'emby-button'; function resetPassword() { const msg = globalize.translate('PasswordResetConfirmation'); - import('confirm').then(({default: confirm}) => { + import('../../../components/confirm/confirm').then(({default: confirm}) => { confirm(msg, globalize.translate('ResetPassword')).then(function () { const userId = params.userId; loading.show(); @@ -163,7 +163,7 @@ import 'emby-button'; function resetEasyPassword() { const msg = globalize.translate('PinCodeResetConfirmation'); - import('confirm').then(({default: confirm}) => { + import('../../../components/confirm/confirm').then(({default: confirm}) => { confirm(msg, globalize.translate('HeaderPinCodeReset')).then(function () { const userId = params.userId; loading.show(); diff --git a/src/controllers/dashboard/users/userprofilespage.js b/src/controllers/dashboard/users/userprofilespage.js index bfd8d96d92..d0c5270d40 100644 --- a/src/controllers/dashboard/users/userprofilespage.js +++ b/src/controllers/dashboard/users/userprofilespage.js @@ -1,20 +1,20 @@ -import loading from 'loading'; -import dom from 'dom'; -import globalize from 'globalize'; -import * as datefns from 'date-fns'; -import dfnshelper from 'dfnshelper'; -import 'paper-icon-button-light'; -import 'cardStyle'; -import 'emby-button'; -import 'indicators'; -import 'flexStyles'; +import loading from '../../../components/loading/loading'; +import dom from '../../../scripts/dom'; +import globalize from '../../../scripts/globalize'; +import { formatDistanceToNow } from 'date-fns'; +import { localeWithSuffix } from '../../../scripts/dfnshelper'; +import '../../../elements/emby-button/paper-icon-button-light'; +import '../../../components/cardbuilder/card.css'; +import '../../../elements/emby-button/emby-button'; +import '../../../components/indicators/indicators.css'; +import '../../../assets/css/flexstyles.css'; /* eslint-disable indent */ function deleteUser(page, id) { const msg = globalize.translate('DeleteUserConfirmation'); - import('confirm').then(({default: confirm}) => { + import('../../../components/confirm/confirm').then(({default: confirm}) => { confirm({ title: globalize.translate('DeleteUser'), text: msg, @@ -55,7 +55,7 @@ import 'flexStyles'; icon: 'delete' }); - import('actionsheet').then(({default: actionsheet}) => { + import('../../../components/actionSheet/actionSheet').then(({default: actionsheet}) => { actionsheet.show({ items: menuItems, positionTo: card, @@ -139,7 +139,7 @@ import 'flexStyles'; // how dates are returned by the server when the session is active and show something like 'Active now', instead of past/future sentences function getLastSeenText(lastActivityDate) { if (lastActivityDate) { - return globalize.translate('LastSeen', datefns.formatDistanceToNow(Date.parse(lastActivityDate), dfnshelper.localeWithSuffix)); + return globalize.translate('LastSeen', formatDistanceToNow(Date.parse(lastActivityDate), localeWithSuffix)); } return ''; diff --git a/src/controllers/edititemmetadata.js b/src/controllers/edititemmetadata.js index dd51ba2581..c28bda2aea 100644 --- a/src/controllers/edititemmetadata.js +++ b/src/controllers/edititemmetadata.js @@ -1,11 +1,11 @@ -import loading from 'loading'; -import 'scripts/editorsidebar'; +import loading from '../components/loading/loading'; +import '../scripts/editorsidebar'; function reload(context, itemId) { loading.show(); if (itemId) { - import('metadataEditor').then(({ default: metadataEditor }) => { + import('../components/metadataEditor/metadataEditor').then((metadataEditor) => { metadataEditor.embed(context.querySelector('.editPageInnerContent'), itemId, ApiClient.serverInfo().Id); }); } else { diff --git a/src/controllers/favorites.js b/src/controllers/favorites.js index fc37f4eef4..01cd75e6e8 100644 --- a/src/controllers/favorites.js +++ b/src/controllers/favorites.js @@ -1,12 +1,13 @@ -import appRouter from 'appRouter'; -import cardBuilder from 'cardBuilder'; -import dom from 'dom'; -import globalize from 'globalize'; -import appHost from 'apphost'; -import layoutManager from 'layoutManager'; -import focusManager from 'focusManager'; -import 'emby-itemscontainer'; -import 'emby-scroller'; +import appRouter from '../components/appRouter'; +import cardBuilder from '../components/cardbuilder/cardBuilder'; +import dom from '../scripts/dom'; +import globalize from '../scripts/globalize'; +import connectionManager from 'jellyfin-apiclient'; +import appHost from '../components/apphost'; +import layoutManager from '../components/layoutManager'; +import focusManager from '../components/focusManager'; +import '../elements/emby-itemscontainer/emby-itemscontainer'; +import '../elements/emby-scroller/emby-scroller'; /* eslint-disable indent */ diff --git a/src/controllers/home.js b/src/controllers/home.js index 72e326e46b..56ad481262 100644 --- a/src/controllers/home.js +++ b/src/controllers/home.js @@ -1,8 +1,8 @@ -import TabbedView from 'tabbedView'; -import globalize from 'globalize'; -import 'emby-tabs'; -import 'emby-button'; -import 'emby-scroller'; +import TabbedView from '../components/tabbedview/tabbedview'; +import globalize from '../scripts/globalize'; +import '../elements/emby-tabs/emby-tabs'; +import '../elements/emby-button/emby-button'; +import '../elements/emby-scroller/emby-scroller'; class HomeView extends TabbedView { constructor(view, params) { diff --git a/src/controllers/hometab.js b/src/controllers/hometab.js index ff56e08d14..65047dbaa8 100644 --- a/src/controllers/hometab.js +++ b/src/controllers/hometab.js @@ -1,8 +1,9 @@ -import * as userSettings from 'userSettings'; -import loading from 'loading'; -import focusManager from 'focusManager'; -import homeSections from 'homeSections'; -import 'emby-itemscontainer'; +import * as userSettings from '../scripts/settings/userSettings'; +import loading from '../components/loading/loading'; +import connectionManager from 'jellyfin-apiclient'; +import focusManager from '../components/focusManager'; +import homeSections from '../components/homesections/homesections'; +import '../elements/emby-itemscontainer/emby-itemscontainer'; class HomeTab { constructor(view, params) { diff --git a/src/controllers/itemDetails/index.js b/src/controllers/itemDetails/index.js index 4c2d29538d..16a77076a5 100644 --- a/src/controllers/itemDetails/index.js +++ b/src/controllers/itemDetails/index.js @@ -1,32 +1,32 @@ -import appHost from 'apphost'; -import loading from 'loading'; -import appRouter from 'appRouter'; -import itemShortcuts from 'itemShortcuts'; -import layoutManager from 'layoutManager'; -import * as userSettings from 'userSettings'; -import cardBuilder from 'cardBuilder'; -import datetime from 'datetime'; -import mediaInfo from 'mediaInfo'; -import backdrop from 'backdrop'; -import listView from 'listView'; -import itemContextMenu from 'itemContextMenu'; -import itemHelper from 'itemHelper'; -import dom from 'dom'; -import indicators from 'indicators'; -import imageLoader from 'imageLoader'; -import libraryMenu from 'libraryMenu'; -import globalize from 'globalize'; -import browser from 'browser'; -import events from 'events'; -import playbackManager from 'playbackManager'; -import 'scrollStyles'; -import 'emby-itemscontainer'; -import 'emby-checkbox'; -import 'emby-button'; -import 'emby-playstatebutton'; -import 'emby-ratingbutton'; -import 'emby-scroller'; -import 'emby-select'; +import appHost from '../../components/apphost'; +import loading from '../../components/loading/loading'; +import appRouter from '../../components/appRouter'; +import layoutManager from '../../components/layoutManager'; +import { connectionManager, events } from 'jellyfin-apiclient'; +import * as userSettings from '../../scripts/settings/userSettings'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import datetime from '../../scripts/datetime'; +import mediaInfo from '../../components/mediainfo/mediainfo'; +import backdrop from '../../components/backdrop/backdrop'; +import listView from '../../components/listview/listview'; +import itemContextMenu from '../../components/itemContextMenu'; +import itemHelper from '../../components/itemHelper'; +import dom from '../../scripts/dom'; +import indicators from '../../components/indicators/indicators'; +import imageLoader from '../../components/images/imageLoader'; +import libraryMenu from '../../scripts/libraryMenu'; +import globalize from '../../scripts/globalize'; +import browser from '../../scripts/browser'; +import playbackManager from '../../components/playback/playbackmanager'; +import '../../assets/css/scrollstyles.css'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; +import '../../elements/emby-checkbox/emby-checkbox'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-playstatebutton/emby-playstatebutton'; +import '../../elements/emby-ratingbutton/emby-ratingbutton'; +import '../../elements/emby-scroller/emby-scroller'; +import '../../elements/emby-select/emby-select'; +import itemShortcuts from '../../components/shortcuts'; function getPromise(apiClient, params) { const id = params.id; @@ -140,7 +140,7 @@ function renderSeriesTimerEditor(page, item, apiClient, user) { } if (user.Policy.EnableLiveTvManagement) { - import('seriesRecordingEditor').then(({ default: seriesRecordingEditor }) => { + import('../../components/recordingcreator/seriesrecordingeditor').then(({ default: seriesRecordingEditor }) => { seriesRecordingEditor.embed(item, apiClient.serverId(), { context: page.querySelector('.seriesRecordingEditor') }); @@ -666,7 +666,7 @@ function reloadFromItem(instance, page, params, item, user) { hideAll(page, 'btnDownload', true); } - import('autoFocuser').then(({ default: autoFocuser }) => { + import('../../components/autoFocuser').then(({ default: autoFocuser }) => { autoFocuser.autoFocus(page); }); } @@ -708,7 +708,7 @@ function showRecordingFields(instance, page, item, user) { const recordingFieldsElement = page.querySelector('.recordingFields'); if (item.Type == 'Program' && user.Policy.EnableLiveTvManagement) { - import('recordingFields').then(({ default: recordingFields }) => { + import('../../components/recordingcreator/recordingfields').then(({ default: recordingFields }) => { instance.currentRecordingFields = new recordingFields({ parent: recordingFieldsElement, programId: item.Id, @@ -1485,13 +1485,13 @@ function renderChildren(page, item) { } function renderItemsByName(page, item) { - import('scripts/itembynamedetailpage').then(() => { + import('../../scripts/itembynamedetailpage').then(() => { window.ItemsByName.renderItems(page, item); }); } function renderPlaylistItems(page, item) { - import('scripts/playlistedit').then(() => { + import('../../scripts/playlistedit').then(() => { PlaylistViewer.render(page, item); }); } @@ -1695,7 +1695,7 @@ function renderCollectionItems(page, parentItem, types, items) { // HACK: Call autoFocuser again because btnPlay may be hidden, but focused by reloadFromItem // FIXME: Sometimes focus does not move until all (?) sections are loaded - import('autoFocuser').then(({ default: autoFocuser }) => { + import('../../components/autoFocuser').then(({ default: autoFocuser }) => { autoFocuser.autoFocus(page); }); } @@ -1770,7 +1770,7 @@ function renderScenes(page, item) { page.querySelector('#scenesCollapsible').classList.remove('hide'); const scenesContent = page.querySelector('#scenesContent'); - import('chaptercardbuilder').then(({ default: chaptercardbuilder }) => { + import('../../components/cardbuilder/chaptercardbuilder').then(({ default: chaptercardbuilder }) => { chaptercardbuilder.buildChapterCards(item, chapters, { itemsContainer: scenesContent, backdropShape: 'overflowBackdrop', @@ -1815,7 +1815,7 @@ function renderCast(page, item) { page.querySelector('#castCollapsible').classList.remove('hide'); const castContent = page.querySelector('#castContent'); - import('peoplecardbuilder').then(({ default: peoplecardbuilder }) => { + import('../../components/cardbuilder/peoplecardbuilder').then(({ default: peoplecardbuilder }) => { peoplecardbuilder.buildPeopleCards(people, { itemsContainer: castContent, coverImage: true, @@ -1863,7 +1863,7 @@ export default function (view, params) { } function splitVersions(instance, page, apiClient, params) { - import('confirm').then(({ default: confirm }) => { + import('../../components/confirm/confirm').then(({ default: confirm }) => { confirm('Are you sure you wish to split the media sources into separate items?', 'Split Media Apart').then(function () { loading.show(); apiClient.ajax({ @@ -1929,7 +1929,7 @@ export default function (view, params) { } function onCancelSeriesTimerClick() { - import('recordingHelper').then(({ default: recordingHelper }) => { + import('../../components/recordingcreator/recordinghelper').then(({ default: recordingHelper }) => { recordingHelper.cancelSeriesTimerWithConfirmation(currentItem.Id, currentItem.ServerId).then(function () { Dashboard.navigate('livetv.html'); }); @@ -1937,7 +1937,7 @@ export default function (view, params) { } function onCancelTimerClick() { - import('recordingHelper').then(({ default: recordingHelper }) => { + import('../../components/recordingcreator/recordinghelper').then(({ default: recordingHelper }) => { recordingHelper.cancelTimer(window.connectionManager.getApiClient(currentItem.ServerId), currentItem.TimerId).then(function () { reload(self, view, params); }); @@ -1949,7 +1949,7 @@ export default function (view, params) { } function onDownloadClick() { - import('fileDownloader').then(({ default: fileDownloader }) => { + import('../../scripts/fileDownloader').then(({ default: fileDownloader }) => { const downloadHref = apiClient.getItemDownloadUrl(currentItem.Id); fileDownloader.download([{ url: downloadHref, diff --git a/src/controllers/list.js b/src/controllers/list.js index 07e07eeb05..d356d800a3 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -1,15 +1,16 @@ -import globalize from 'globalize'; -import listView from 'listView'; -import layoutManager from 'layoutManager'; -import * as userSettings from 'userSettings'; -import focusManager from 'focusManager'; -import cardBuilder from 'cardBuilder'; -import loading from 'loading'; -import AlphaNumericShortcuts from 'alphaNumericShortcuts'; -import playbackManager from 'playbackManager'; -import AlphaPicker from 'alphaPicker'; -import 'emby-itemscontainer'; -import 'emby-scroller'; +import globalize from '../scripts/globalize'; +import listView from '../components/listview/listview'; +import layoutManager from '../components/layoutManager'; +import * as userSettings from '../scripts/settings/userSettings'; +import focusManager from '../components/focusManager'; +import cardBuilder from '../components/cardbuilder/cardBuilder'; +import loading from '../components/loading/loading'; +import connectionManager from 'jellyfin-apiclient'; +import AlphaNumericShortcuts from '../scripts/alphanumericshortcuts'; +import playbackManager from '../components/playback/playbackmanager'; +import AlphaPicker from '../components/alphaPicker/alphaPicker'; +import '../elements/emby-itemscontainer/emby-itemscontainer'; +import '../elements/emby-scroller/emby-scroller'; /* eslint-disable indent */ @@ -345,7 +346,7 @@ import 'emby-scroller'; function showViewSettingsMenu() { const instance = this; - import('viewSettings').then(({default: ViewSettings}) => { + import('../components/viewSettings/viewSettings').then((ViewSettings) => { new ViewSettings().show({ settingsKey: instance.getSettingsKey(), settings: instance.getViewSettings(), @@ -360,7 +361,7 @@ import 'emby-scroller'; function showFilterMenu() { const instance = this; - import('filterMenu').then(({default: FilterMenu}) => { + import('../components/filtermenu/filtermenu').then(({default: FilterMenu}) => { new FilterMenu().show({ settingsKey: instance.getSettingsKey(), settings: instance.getFilters(), @@ -379,7 +380,7 @@ import 'emby-scroller'; function showSortMenu() { const instance = this; - import('sortMenu').then(({default: SortMenu}) => { + import('../components/sortmenu/sortmenu').then((SortMenu) => { new SortMenu().show({ settingsKey: instance.getSettingsKey(), settings: instance.getSortValues(), @@ -397,7 +398,7 @@ import 'emby-scroller'; function onNewItemClick() { const instance = this; - import('playlistEditor').then(({default: playlistEditor}) => { + import('../components/playlisteditor/playlisteditor').then((playlistEditor) => { new playlistEditor({ items: [], serverId: instance.params.serverId diff --git a/src/controllers/livetv/livetvchannels.js b/src/controllers/livetv/livetvchannels.js index 278200c634..9de6e71785 100644 --- a/src/controllers/livetv/livetvchannels.js +++ b/src/controllers/livetv/livetvchannels.js @@ -1,10 +1,10 @@ -import cardBuilder from 'cardBuilder'; -import imageLoader from 'imageLoader'; -import libraryBrowser from 'libraryBrowser'; -import loading from 'loading'; -import events from 'events'; -import * as userSettings from 'userSettings'; -import 'emby-itemscontainer'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import imageLoader from '../../components/images/imageLoader'; +import libraryBrowser from '../../scripts/libraryBrowser'; +import loading from '../../components/loading/loading'; +import events from 'jellyfin-apiclient'; +import * as userSettings from '../../scripts/settings/userSettings'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; export default function (view, params, tabContent) { function getPageData() { @@ -115,7 +115,7 @@ export default function (view, params, tabContent) { loading.hide(); isLoading = false; - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(view); }); }); diff --git a/src/controllers/livetv/livetvguide.js b/src/controllers/livetv/livetvguide.js index f8b49bd22a..c56d4ebd04 100644 --- a/src/controllers/livetv/livetvguide.js +++ b/src/controllers/livetv/livetvguide.js @@ -1,4 +1,4 @@ -import tvguide from 'tvguide'; +import tvguide from '../../components/guide/guide'; export default function (view, params, tabContent) { let guideInstance; diff --git a/src/controllers/livetv/livetvrecordings.js b/src/controllers/livetv/livetvrecordings.js index ec2f57e14f..23197da6cf 100644 --- a/src/controllers/livetv/livetvrecordings.js +++ b/src/controllers/livetv/livetvrecordings.js @@ -1,9 +1,9 @@ -import loading from 'loading'; -import cardBuilder from 'cardBuilder'; -import imageLoader from 'imageLoader'; -import 'scripts/livetvcomponents'; -import 'listViewStyle'; -import 'emby-itemscontainer'; +import loading from '../../components/loading/loading'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import imageLoader from '../../components/images/imageLoader'; +import '../../scripts/livetvcomponents'; +import '../../components/listview/listview.css'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; function renderRecordings(elem, recordings, cardOptions, scrollX) { if (!elem) { diff --git a/src/controllers/livetv/livetvschedule.js b/src/controllers/livetv/livetvschedule.js index d7bfbad059..2e795f0c7d 100644 --- a/src/controllers/livetv/livetvschedule.js +++ b/src/controllers/livetv/livetvschedule.js @@ -1,10 +1,10 @@ -import layoutManager from 'layoutManager'; -import cardBuilder from 'cardBuilder'; -import imageLoader from 'imageLoader'; -import loading from 'loading'; -import 'scripts/livetvcomponents'; -import 'emby-button'; -import 'emby-itemscontainer'; +import layoutManager from '../../components/layoutManager'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import imageLoader from '../../components/images/imageLoader'; +import loading from '../../components/loading/loading'; +import '../../scripts/livetvcomponents'; +import '../../elements/emby-button/emby-button'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; function enableScrollX() { return !layoutManager.desktop; diff --git a/src/controllers/livetv/livetvseriestimers.js b/src/controllers/livetv/livetvseriestimers.js index 4f6bfaaa6a..3029fca5a6 100644 --- a/src/controllers/livetv/livetvseriestimers.js +++ b/src/controllers/livetv/livetvseriestimers.js @@ -1,8 +1,8 @@ -import cardBuilder from 'cardBuilder'; -import imageLoader from 'imageLoader'; -import loading from 'loading'; -import 'paper-icon-button-light'; -import 'emby-button'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import imageLoader from '../../components/images/imageLoader'; +import loading from '../../components/loading/loading'; +import '../../elements/emby-button/paper-icon-button-light'; +import '../../elements/emby-button/emby-button'; function renderTimers(context, timers) { const html = cardBuilder.getCardsHtml({ diff --git a/src/controllers/livetv/livetvsuggested.js b/src/controllers/livetv/livetvsuggested.js index 346630012a..d820715f5d 100644 --- a/src/controllers/livetv/livetvsuggested.js +++ b/src/controllers/livetv/livetvsuggested.js @@ -1,15 +1,15 @@ -import layoutManager from 'layoutManager'; -import * as userSettings from 'userSettings'; -import inputManager from 'inputManager'; -import loading from 'loading'; -import globalize from 'globalize'; -import * as mainTabsManager from 'mainTabsManager'; -import cardBuilder from 'cardBuilder'; -import imageLoader from 'imageLoader'; -import 'scrollStyles'; -import 'emby-itemscontainer'; -import 'emby-tabs'; -import 'emby-button'; +import layoutManager from '../../components/layoutManager'; +import * as userSettings from '../../scripts/settings/userSettings'; +import inputManager from '../../scripts/inputManager'; +import loading from '../../components/loading/loading'; +import globalize from '../../scripts/globalize'; +import * as mainTabsManager from '../../components/maintabsmanager'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import imageLoader from '../../components/images/imageLoader'; +import '../../assets/css/scrollstyles.css'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; +import '../../elements/emby-tabs/emby-tabs'; +import '../../elements/emby-button/emby-button'; function enableScrollX() { return !layoutManager.desktop; @@ -60,7 +60,7 @@ function loadRecommendedPrograms(page) { }); loading.hide(); - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(page); }); }); diff --git a/src/controllers/livetvguideprovider.js b/src/controllers/livetvguideprovider.js index 6ab195a088..750bbff479 100644 --- a/src/controllers/livetvguideprovider.js +++ b/src/controllers/livetvguideprovider.js @@ -1,6 +1,6 @@ -import events from 'events'; -import loading from 'loading'; -import globalize from 'globalize'; +import events from 'jellyfin-apiclient'; +import loading from '../components/loading/loading'; +import globalize from '../scripts/globalize'; function onListingsSubmitted() { Dashboard.navigate('livetvstatus.html'); @@ -17,7 +17,7 @@ function init(page, type, providerId) { } function loadTemplate(page, type, providerId) { - import('text!./../components/tvproviders/' + type + '.template.html').then(({default: html}) => { + import('./../components/tvproviders/' + type + '.template.html').then(({default: html}) => { page.querySelector('.providerTemplate').innerHTML = globalize.translateHtml(html); init(page, type, providerId); }); diff --git a/src/controllers/livetvsettings.js b/src/controllers/livetvsettings.js index 29ec4a10a5..8946a44520 100644 --- a/src/controllers/livetvsettings.js +++ b/src/controllers/livetvsettings.js @@ -1,7 +1,7 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import globalize from 'globalize'; -import 'emby-button'; +import 'jquery'; +import loading from '../components/loading/loading'; +import globalize from '../scripts/globalize'; +import '../elements/emby-button/emby-button'; function loadPage(page, config) { $('.liveTvSettingsForm', page).show(); @@ -50,7 +50,7 @@ function showSaveMessage(recordingPathChanged) { } if (msg) { - import('alert').then(({default: alert}) => { + import('../components/alert').then(({default: alert}) => { alert(msg); }); } @@ -61,7 +61,7 @@ export default function () { const page = this; $('.liveTvSettingsForm').off('submit', onSubmit).on('submit', onSubmit); $('#btnSelectRecordingPath', page).on('click.selectDirectory', function () { - import('directorybrowser').then(({default: directoryBrowser}) => { + import('../components/directorybrowser/directorybrowser').then(({default: directoryBrowser}) => { const picker = new directoryBrowser(); picker.show({ callback: function (path) { @@ -76,7 +76,7 @@ export default function () { }); }); $('#btnSelectMovieRecordingPath', page).on('click.selectDirectory', function () { - import('directorybrowser').then(({default: directoryBrowser}) => { + import('../components/directorybrowser/directorybrowser').then(({default: directoryBrowser}) => { const picker = new directoryBrowser(); picker.show({ callback: function (path) { @@ -91,7 +91,7 @@ export default function () { }); }); $('#btnSelectSeriesRecordingPath', page).on('click.selectDirectory', function () { - import('directorybrowser').then(({default: directoryBrowser}) => { + import('../components/directorybrowser/directorybrowser').then(({default: directoryBrowser}) => { const picker = new directoryBrowser(); picker.show({ callback: function (path) { @@ -106,7 +106,7 @@ export default function () { }); }); $('#btnSelectPostProcessorPath', page).on('click.selectDirectory', function () { - import('directorybrowser').then(({default: directoryBrowser}) => { + import('../components/directorybrowser/directorybrowser').then(({default: directoryBrowser}) => { const picker = new directoryBrowser(); picker.show({ includeFiles: true, diff --git a/src/controllers/livetvstatus.js b/src/controllers/livetvstatus.js index dcf15adf07..ac44336cc0 100644 --- a/src/controllers/livetvstatus.js +++ b/src/controllers/livetvstatus.js @@ -1,16 +1,16 @@ -import $ from 'jQuery'; -import globalize from 'globalize'; -import taskButton from 'scripts/taskbutton'; -import dom from 'dom'; -import layoutManager from 'layoutManager'; -import loading from 'loading'; -import browser from 'browser'; -import 'listViewStyle'; -import 'flexStyles'; -import 'emby-itemscontainer'; -import 'cardStyle'; -import 'material-icons'; -import 'emby-button'; +import 'jquery'; +import globalize from '../scripts/globalize'; +import taskButton from '../scripts/taskbutton'; +import dom from '../scripts/dom'; +import layoutManager from '../components/layoutManager'; +import loading from '../components/loading/loading'; +import browser from '../scripts/browser'; +import '../components/listview/listview.css'; +import '../assets/css/flexstyles.css'; +import '../elements/emby-itemscontainer/emby-itemscontainer'; +import '../components/cardbuilder/card.css'; +import 'material-design-icons-iconfont'; +import '../elements/emby-button/emby-button'; const enableFocusTransform = !browser.slow && !browser.edge; @@ -56,7 +56,7 @@ function renderDevices(page, devices) { function deleteDevice(page, id) { const message = globalize.translate('MessageConfirmDeleteTunerDevice'); - import('confirm').then(({default: confirm}) => { + import('../components/confirm/confirm').then(({default: confirm}) => { confirm(message, globalize.translate('HeaderDeleteDevice')).then(function () { loading.show(); ApiClient.ajax({ @@ -145,7 +145,7 @@ function showProviderOptions(page, providerId, button) { id: 'map' }); - import('actionsheet').then(({default: actionsheet}) => { + import('../components/actionSheet/actionSheet').then(({default: actionsheet}) => { actionsheet.show({ items: items, positionTo: button @@ -163,7 +163,7 @@ function showProviderOptions(page, providerId, button) { } function mapChannels(page, providerId) { - import('components/channelMapper/channelMapper').then(({default: channelMapper}) => { + import('../components/channelMapper/channelMapper').then(({default: channelMapper}) => { new channelMapper({ serverId: ApiClient.serverInfo().Id, providerId: providerId @@ -174,7 +174,7 @@ function mapChannels(page, providerId) { function deleteProvider(page, id) { const message = globalize.translate('MessageConfirmDeleteGuideProvider'); - import('confirm').then(({default: confirm}) => { + import('../components/confirm/confirm').then(({default: confirm}) => { confirm(message, globalize.translate('HeaderDeleteProvider')).then(function () { loading.show(); ApiClient.ajax({ @@ -237,7 +237,7 @@ function addProvider(button) { id: 'xmltv' }); - import('actionsheet').then(({default: actionsheet}) => { + import('../components/actionSheet/actionSheet').then(({default: actionsheet}) => { actionsheet.show({ items: menuItems, positionTo: button, @@ -263,7 +263,7 @@ function showDeviceMenu(button, tunerDeviceId) { id: 'edit' }); - import('actionsheet').then(({default: actionsheet}) => { + import('../components/actionSheet/actionSheet').then(({default: actionsheet}) => { actionsheet.show({ items: items, positionTo: button diff --git a/src/controllers/livetvtuner.js b/src/controllers/livetvtuner.js index 0e3b2b689e..383e52faf7 100644 --- a/src/controllers/livetvtuner.js +++ b/src/controllers/livetvtuner.js @@ -1,10 +1,10 @@ -import globalize from 'globalize'; -import loading from 'loading'; -import dom from 'dom'; -import 'emby-input'; -import 'emby-button'; -import 'emby-checkbox'; -import 'emby-select'; +import globalize from '../scripts/globalize'; +import loading from '../components/loading/loading'; +import dom from '../scripts/dom'; +import '../elements/emby-input/emby-input'; +import '../elements/emby-button/emby-button'; +import '../elements/emby-checkbox/emby-checkbox'; +import '../elements/emby-select/emby-select'; function isM3uVariant(type) { return ['nextpvr'].indexOf(type || '') !== -1; @@ -102,7 +102,7 @@ function submitForm(page) { } function getDetectedDevice() { - return import('tunerPicker').then(({default: tunerPicker}) => { + return import('../components/tunerPicker').then((tunerPicker) => { return new tunerPicker().show({ serverId: ApiClient.serverId() }); @@ -211,7 +211,7 @@ export default function (view, params) { }); }); view.querySelector('.btnSelectPath').addEventListener('click', function () { - import('directorybrowser').then(({default: directorybrowser}) => { + import('../components/directorybrowser/directorybrowser').then(({default: directorybrowser}) => { const picker = new directorybrowser(); picker.show({ includeFiles: true, diff --git a/src/controllers/movies/moviecollections.js b/src/controllers/movies/moviecollections.js index 6aed25f9a8..cfabe016ca 100644 --- a/src/controllers/movies/moviecollections.js +++ b/src/controllers/movies/moviecollections.js @@ -1,11 +1,11 @@ -import loading from 'loading'; -import libraryBrowser from 'libraryBrowser'; -import imageLoader from 'imageLoader'; -import listView from 'listView'; -import cardBuilder from 'cardBuilder'; -import * as userSettings from 'userSettings'; -import globalize from 'globalize'; -import 'emby-itemscontainer'; +import loading from '../../components/loading/loading'; +import libraryBrowser from '../../scripts/libraryBrowser'; +import imageLoader from '../../components/images/imageLoader'; +import listView from '../../components/listview/listview'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import * as userSettings from '../../scripts/settings/userSettings'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; /* eslint-disable indent */ @@ -193,7 +193,7 @@ import 'emby-itemscontainer'; loading.hide(); isLoading = false; - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(page); }); }); @@ -246,7 +246,7 @@ import 'emby-itemscontainer'; reloadItems(tabContent); }); tabContent.querySelector('.btnNewCollection').addEventListener('click', () => { - import('collectionEditor').then(({default: collectionEditor}) => { + import('../../components/collectionEditor/collectionEditor').then(({default: collectionEditor}) => { const serverId = ApiClient.serverInfo().Id; new collectionEditor({ items: [], diff --git a/src/controllers/movies/moviegenres.js b/src/controllers/movies/moviegenres.js index ca02ede36d..2b106dc361 100644 --- a/src/controllers/movies/moviegenres.js +++ b/src/controllers/movies/moviegenres.js @@ -1,11 +1,11 @@ -import layoutManager from 'layoutManager'; -import loading from 'loading'; -import libraryBrowser from 'libraryBrowser'; -import cardBuilder from 'cardBuilder'; -import lazyLoader from 'lazyLoader'; -import globalize from 'globalize'; -import appRouter from 'appRouter'; -import 'emby-button'; +import layoutManager from '../../components/layoutManager'; +import loading from '../../components/loading/loading'; +import libraryBrowser from '../../scripts/libraryBrowser'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import lazyLoader from '../../components/lazyLoader/lazyLoaderIntersectionObserver'; +import globalize from '../../scripts/globalize'; +import appRouter from '../../components/appRouter'; +import '../../elements/emby-button/emby-button'; /* eslint-disable indent */ diff --git a/src/controllers/movies/movies.js b/src/controllers/movies/movies.js index 09be5a71f0..648290abe1 100644 --- a/src/controllers/movies/movies.js +++ b/src/controllers/movies/movies.js @@ -1,12 +1,12 @@ -import loading from 'loading'; -import * as userSettings from 'userSettings'; -import events from 'events'; -import libraryBrowser from 'libraryBrowser'; -import AlphaPicker from 'alphaPicker'; -import listView from 'listView'; -import cardBuilder from 'cardBuilder'; -import globalize from 'globalize'; -import 'emby-itemscontainer'; +import loading from '../../components/loading/loading'; +import * as userSettings from '../../scripts/settings/userSettings'; +import events from 'jellyfin-apiclient'; +import libraryBrowser from '../../scripts/libraryBrowser'; +import { AlphaPicker } from '../../components/alphaPicker/alphaPicker'; +import listView from '../../components/listview/listview'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; /* eslint-disable indent */ @@ -91,7 +91,7 @@ import 'emby-itemscontainer'; isLoading = false; loading.hide(); - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(tabContent); }); } @@ -278,7 +278,7 @@ import 'emby-itemscontainer'; query = userSettings.loadQuerySettings(savedQueryKey, query); this.showFilterMenu = function () { - import('components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { + import('../../components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { const filterDialog = new filterDialogFactory({ query: query, mode: 'movies', diff --git a/src/controllers/movies/moviesrecommended.js b/src/controllers/movies/moviesrecommended.js index 80e391c5ef..1270e9f134 100644 --- a/src/controllers/movies/moviesrecommended.js +++ b/src/controllers/movies/moviesrecommended.js @@ -1,18 +1,19 @@ -import events from 'events'; -import layoutManager from 'layoutManager'; -import inputManager from 'inputManager'; -import * as userSettings from 'userSettings'; -import libraryMenu from 'libraryMenu'; -import * as mainTabsManager from 'mainTabsManager'; -import cardBuilder from 'cardBuilder'; -import dom from 'dom'; -import imageLoader from 'imageLoader'; -import playbackManager from 'playbackManager'; -import globalize from 'globalize'; -import 'emby-scroller'; -import 'emby-itemscontainer'; -import 'emby-tabs'; -import 'emby-button'; + +import events from 'jellyfin-apiclient'; +import layoutManager from '../../components/layoutManager'; +import inputManager from '../../scripts/inputManager'; +import * as userSettings from '../../scripts/settings/userSettings'; +import libraryMenu from '../../scripts/libraryMenu'; +import * as mainTabsManager from '../../components/maintabsmanager'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import dom from '../../scripts/dom'; +import imageLoader from '../../components/images/imageLoader'; +import playbackManager from '../../components/playback/playbackmanager'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-scroller/emby-scroller'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; +import '../../elements/emby-tabs/emby-tabs'; +import '../../elements/emby-button/emby-button'; /* eslint-disable indent */ @@ -182,7 +183,7 @@ import 'emby-button'; } function autoFocus(page) { - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(page); }); } diff --git a/src/controllers/movies/movietrailers.js b/src/controllers/movies/movietrailers.js index def55d919a..4f92b139bc 100644 --- a/src/controllers/movies/movietrailers.js +++ b/src/controllers/movies/movietrailers.js @@ -1,13 +1,13 @@ -import loading from 'loading'; -import events from 'events'; -import libraryBrowser from 'libraryBrowser'; -import imageLoader from 'imageLoader'; -import AlphaPicker from 'alphaPicker'; -import listView from 'listView'; -import cardBuilder from 'cardBuilder'; -import * as userSettings from 'userSettings'; -import globalize from 'globalize'; -import 'emby-itemscontainer'; +import loading from '../../components/loading/loading'; +import events from 'jellyfin-apiclient'; +import libraryBrowser from '../../scripts/libraryBrowser'; +import imageLoader from '../../components/images/imageLoader'; +import { AlphaPicker } from '../../components/alphaPicker/alphaPicker'; +import listView from '../../components/listview/listview'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import * as userSettings from '../../scripts/settings/userSettings'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; /* eslint-disable indent */ @@ -192,7 +192,7 @@ import 'emby-itemscontainer'; let isLoading = false; this.showFilterMenu = function () { - import('components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { + import('../../components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { const filterDialog = new filterDialogFactory({ query: getQuery(tabContent), mode: 'movies', diff --git a/src/controllers/music/musicalbums.js b/src/controllers/music/musicalbums.js index 55e59b6289..d9abe48fe7 100644 --- a/src/controllers/music/musicalbums.js +++ b/src/controllers/music/musicalbums.js @@ -1,14 +1,14 @@ -import playbackManager from 'playbackManager'; -import loading from 'loading'; -import events from 'events'; -import libraryBrowser from 'libraryBrowser'; -import imageLoader from 'imageLoader'; -import AlphaPicker from 'alphaPicker'; -import listView from 'listView'; -import cardBuilder from 'cardBuilder'; -import * as userSettings from 'userSettings'; -import globalize from 'globalize'; -import 'emby-itemscontainer'; +import playbackManager from '../../components/playback/playbackmanager'; +import loading from '../../components/loading/loading'; +import events from 'jellyfin-apiclient'; +import libraryBrowser from '../../scripts/libraryBrowser'; +import imageLoader from '../../components/images/imageLoader'; +import AlphaPicker from '../../components/alphaPicker/alphaPicker'; +import listView from '../../components/listview/listview'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import * as userSettings from '../../scripts/settings/userSettings'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; /* eslint-disable indent */ @@ -179,7 +179,7 @@ import 'emby-itemscontainer'; loading.hide(); isLoading = false; - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(tabContent); }); }); @@ -204,7 +204,7 @@ import 'emby-itemscontainer'; let isLoading = false; this.showFilterMenu = function () { - import('components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { + import('../../components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { const filterDialog = new filterDialogFactory({ query: getQuery(), mode: 'albums', diff --git a/src/controllers/music/musicartists.js b/src/controllers/music/musicartists.js index 3517437622..a7c01220cd 100644 --- a/src/controllers/music/musicartists.js +++ b/src/controllers/music/musicartists.js @@ -1,12 +1,12 @@ -import loading from 'loading'; -import events from 'events'; -import libraryBrowser from 'libraryBrowser'; -import imageLoader from 'imageLoader'; -import AlphaPicker from 'alphaPicker'; -import listView from 'listView'; -import cardBuilder from 'cardBuilder'; -import * as userSettings from 'userSettings'; -import 'emby-itemscontainer'; +import loading from '../../components/loading/loading'; +import events from 'jellyfin-apiclient'; +import libraryBrowser from '../../scripts/libraryBrowser'; +import imageLoader from '../../components/images/imageLoader'; +import { AlphaPicker } from '../../components/alphaPicker/alphaPicker'; +import listView from '../../components/listview/listview'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import * as userSettings from '../../scripts/settings/userSettings'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; /* eslint-disable indent */ @@ -161,7 +161,7 @@ import 'emby-itemscontainer'; loading.hide(); isLoading = false; - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(tabContent); }); }); @@ -176,7 +176,7 @@ import 'emby-itemscontainer'; let isLoading = false; this.showFilterMenu = function () { - import('components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { + import('../../components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { const filterDialog = new filterDialogFactory({ query: getQuery(tabContent), mode: this.mode, diff --git a/src/controllers/music/musicgenres.js b/src/controllers/music/musicgenres.js index 2cd9e2114b..c0e48e9a52 100644 --- a/src/controllers/music/musicgenres.js +++ b/src/controllers/music/musicgenres.js @@ -1,7 +1,7 @@ -import libraryBrowser from 'libraryBrowser'; -import cardBuilder from 'cardBuilder'; -import imageLoader from 'imageLoader'; -import loading from 'loading'; +import libraryBrowser from '../../scripts/libraryBrowser'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import imageLoader from '../../components/images/imageLoader'; +import loading from '../../components/loading/loading'; /* eslint-disable indent */ @@ -92,7 +92,7 @@ import loading from 'loading'; libraryBrowser.saveQueryValues(getSavedQueryKey(), query); loading.hide(); - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(context); }); }); diff --git a/src/controllers/music/musicplaylists.js b/src/controllers/music/musicplaylists.js index 67e6a959eb..2d98aa5a99 100644 --- a/src/controllers/music/musicplaylists.js +++ b/src/controllers/music/musicplaylists.js @@ -1,7 +1,7 @@ -import libraryBrowser from 'libraryBrowser'; -import cardBuilder from 'cardBuilder'; -import imageLoader from 'imageLoader'; -import loading from 'loading'; +import libraryBrowser from '../../scripts/libraryBrowser'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import imageLoader from '../../components/images/imageLoader'; +import loading from '../../components/loading/loading'; /* eslint-disable indent */ @@ -63,7 +63,7 @@ import loading from 'loading'; libraryBrowser.saveQueryValues(getSavedQueryKey(), query); loading.hide(); - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(context); }); }); diff --git a/src/controllers/music/musicrecommended.js b/src/controllers/music/musicrecommended.js index 32137ccaa8..d0f7010417 100644 --- a/src/controllers/music/musicrecommended.js +++ b/src/controllers/music/musicrecommended.js @@ -1,19 +1,19 @@ -import browser from 'browser'; -import layoutManager from 'layoutManager'; -import * as userSettings from 'userSettings'; -import inputManager from 'inputManager'; -import loading from 'loading'; -import cardBuilder from 'cardBuilder'; -import dom from 'dom'; -import imageLoader from 'imageLoader'; -import libraryMenu from 'libraryMenu'; -import * as mainTabsManager from 'mainTabsManager'; -import globalize from 'globalize'; -import 'scrollStyles'; -import 'emby-itemscontainer'; -import 'emby-tabs'; -import 'emby-button'; -import 'flexStyles'; +import browser from '../../scripts/browser'; +import layoutManager from '../../components/layoutManager'; +import * as userSettings from '../../scripts/settings/userSettings'; +import inputManager from '../../scripts/inputManager'; +import loading from '../../components/loading/loading'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import dom from '../../scripts/dom'; +import imageLoader from '../../components/images/imageLoader'; +import libraryMenu from '../../scripts/libraryMenu'; +import * as mainTabsManager from '../../components/maintabsmanager'; +import globalize from '../../scripts/globalize'; +import '../../assets/css/scrollstyles.css'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; +import '../../elements/emby-tabs/emby-tabs'; +import '../../elements/emby-button/emby-button'; +import '../../assets/css/flexstyles.css'; /* eslint-disable indent */ @@ -74,7 +74,7 @@ import 'flexStyles'; imageLoader.lazyChildren(elem); loading.hide(); - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(page); }); }); @@ -170,7 +170,7 @@ import 'flexStyles'; loadRecentlyPlayed(tabContent, parentId); loadFrequentlyPlayed(tabContent, parentId); - import('components/favoriteitems').then(({default: favoriteItems}) => { + import('../../components/favoriteitems').then(({default: favoriteItems}) => { favoriteItems.render(tabContent, ApiClient.getCurrentUserId(), parentId, ['favoriteArtists', 'favoriteAlbums', 'favoriteSongs']); }); } diff --git a/src/controllers/music/songs.js b/src/controllers/music/songs.js index d30c74deb8..cc526df6b4 100644 --- a/src/controllers/music/songs.js +++ b/src/controllers/music/songs.js @@ -1,11 +1,12 @@ -import events from 'events'; -import libraryBrowser from 'libraryBrowser'; -import imageLoader from 'imageLoader'; -import listView from 'listView'; -import loading from 'loading'; -import * as userSettings from 'userSettings'; -import globalize from 'globalize'; -import 'emby-itemscontainer'; + +import events from 'jellyfin-apiclient'; +import libraryBrowser from '../../scripts/libraryBrowser'; +import imageLoader from '../../components/images/imageLoader'; +import listView from '../../components/listview/listview'; +import loading from '../../components/loading/loading'; +import * as userSettings from '../../scripts/settings/userSettings'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; /* eslint-disable indent */ @@ -119,7 +120,7 @@ import 'emby-itemscontainer'; loading.hide(); isLoading = false; - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(page); }); }); @@ -130,7 +131,7 @@ import 'emby-itemscontainer'; let isLoading = false; self.showFilterMenu = function () { - import('components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { + import('../../components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { const filterDialog = new filterDialogFactory({ query: getQuery(tabContent), mode: 'songs', diff --git a/src/controllers/playback/queue/index.js b/src/controllers/playback/queue/index.js index 581b5f4b8a..8bece4eb3f 100644 --- a/src/controllers/playback/queue/index.js +++ b/src/controllers/playback/queue/index.js @@ -1,6 +1,6 @@ -import remotecontrolFactory from 'components/remotecontrol/remotecontrol'; -import libraryMenu from 'libraryMenu'; -import 'emby-button'; +import remotecontrolFactory from '../../../components/remotecontrol/remotecontrol'; +import libraryMenu from '../../../scripts/libraryMenu'; +import '../../../elements/emby-button/emby-button'; export default function (view, params) { const remoteControl = new remotecontrolFactory(); diff --git a/src/controllers/playback/video/index.js b/src/controllers/playback/video/index.js index 492f4aeee9..5e99971a84 100644 --- a/src/controllers/playback/video/index.js +++ b/src/controllers/playback/video/index.js @@ -1,22 +1,22 @@ -import playbackManager from 'playbackManager'; -import dom from 'dom'; -import inputManager from 'inputManager'; -import mouseManager from 'mouseManager'; -import datetime from 'datetime'; -import itemHelper from 'itemHelper'; -import mediaInfo from 'mediaInfo'; -import focusManager from 'focusManager'; -import events from 'events'; -import browser from 'browser'; -import globalize from 'globalize'; -import appHost from 'apphost'; -import layoutManager from 'layoutManager'; -import * as userSettings from 'userSettings'; -import keyboardnavigation from 'keyboardnavigation'; -import 'scrollStyles'; -import 'emby-slider'; -import 'paper-icon-button-light'; -import 'css!assets/css/videoosd'; +import playbackManager from '../../../components/playback/playbackmanager'; +import dom from '../../../scripts/dom'; +import inputManager from '../../../scripts/inputManager'; +import mouseManager from '../../../scripts/mouseManager'; +import datetime from '../../../scripts/datetime'; +import itemHelper from '../../../components/itemHelper'; +import mediaInfo from '../../../components/mediainfo/mediainfo'; +import focusManager from '../../../components/focusManager'; +import { connectionManager, events } from 'jellyfin-apiclient';; +import browser from '../../../scripts/browser'; +import globalize from '../../../scripts/globalize'; +import appHost from '../../../components/apphost'; +import layoutManager from '../../../components/layoutManager'; +import * as userSettings from '../../../scripts/settings/userSettings'; +import keyboardnavigation from '../../../scripts/keyboardNavigation'; +import '../../../assets/css/scrollstyles.css'; +import '../../../elements/emby-slider/emby-slider'; +import '../../../elements/emby-button/paper-icon-button-light'; +import '../../../assets/css/videoosd.css'; /* eslint-disable indent */ @@ -99,7 +99,7 @@ import 'css!assets/css/videoosd'; window.connectionManager.getApiClient(item.ServerId).getCurrentUser().then(function (user) { if (user.Policy.EnableLiveTvManagement) { - import('recordingButton').then(({default: RecordingButton}) => { + import('../../../components/recordingcreator/recordingbutton').then((RecordingButton) => { if (recordingButtonManager) { return void recordingButtonManager.refreshItem(item); } @@ -613,7 +613,7 @@ import 'css!assets/css/videoosd'; } function showComingUpNext(player) { - import('upNextDialog').then(({default: UpNextDialog}) => { + import('../../../components/upnextdialog/upnextdialog').then((UpNextDialog) => { if (!(currentVisibleMenu || currentUpNextDialog)) { currentVisibleMenu = 'upnext'; comingUpNextDisplayed = true; @@ -852,7 +852,7 @@ import 'css!assets/css/videoosd'; function onSettingsButtonClick(e) { const btn = this; - import('playerSettingsMenu').then(({default: playerSettingsMenu}) => { + import('../../../components/playback/playersettingsmenu').then((playerSettingsMenu) => { const player = currentPlayer; if (player) { @@ -889,7 +889,7 @@ import 'css!assets/css/videoosd'; } function toggleStats() { - import('playerStats').then(({default: PlayerStats}) => { + import('../../../components/playerstats/playerstats').then((PlayerStats) => { const player = currentPlayer; if (player) { @@ -929,7 +929,7 @@ import 'css!assets/css/videoosd'; }); const positionTo = this; - import('actionsheet').then(({default: actionsheet}) => { + import('../../../components/actionSheet/actionSheet').then(({default: actionsheet}) => { actionsheet.show({ items: menuItems, title: globalize.translate('Audio'), @@ -975,7 +975,7 @@ import 'css!assets/css/videoosd'; }); const positionTo = this; - import('actionsheet').then(({default: actionsheet}) => { + import('../../../components/actionSheet/actionSheet').then(({default: actionsheet}) => { actionsheet.show({ title: globalize.translate('Subtitles'), items: menuItems, @@ -997,7 +997,7 @@ import 'css!assets/css/videoosd'; } function toggleSubtitleSync(action) { - import('subtitleSync').then(({default: SubtitleSync}) => { + import('../../../components/subtitlesync/subtitlesync').then((SubtitleSync) => { const player = currentPlayer; if (subtitleSyncOverlay) { subtitleSyncOverlay.toggle(action); @@ -1228,7 +1228,7 @@ import 'css!assets/css/videoosd'; let playPauseClickTimeout; function onViewHideStopPlayback() { if (playbackManager.isPlayingVideo()) { - import('shell').then(({default: shell}) => { + import('../../../scripts/shell').then((shell) => { shell.disableFullscreen(); }); @@ -1248,7 +1248,7 @@ import 'css!assets/css/videoosd'; } } - import('shell').then(({default: shell}) => { + import('../../../scripts/shell').then(({default: shell}) => { shell.enableFullscreen(); }); @@ -1337,7 +1337,7 @@ import 'css!assets/css/videoosd'; passive: true }); } catch (e) { - import('appRouter').then(({default: appRouter}) => { + import('../../../components/appRouter').then(({default: appRouter}) => { appRouter.goHome(); }); } @@ -1548,7 +1548,7 @@ import 'css!assets/css/videoosd'; if (browser.touch) { (function () { - import('touchHelper').then(({default: TouchHelper}) => { + import('../../../scripts/touchHelper').then((TouchHelper) => { self.touchHelper = new TouchHelper(view, { swipeYThreshold: 30, triggerOnMove: true, diff --git a/src/controllers/searchpage.js b/src/controllers/searchpage.js index ffb7fbac0b..9b40f6a064 100644 --- a/src/controllers/searchpage.js +++ b/src/controllers/searchpage.js @@ -1,6 +1,6 @@ -import SearchFields from 'searchFields'; -import SearchResults from 'searchResults'; -import events from 'events'; +import SearchFields from '../components/search/searchfields'; +import SearchResults from '../components/search/searchresults'; +import events from 'jellyfin-apiclient'; export default function (view, params) { function onSearch(e, value) { diff --git a/src/controllers/session/addServer/index.js b/src/controllers/session/addServer/index.js index 472d1274a9..1a16d7374e 100644 --- a/src/controllers/session/addServer/index.js +++ b/src/controllers/session/addServer/index.js @@ -1,7 +1,7 @@ -import appSettings from 'appSettings'; -import loading from 'loading'; -import globalize from 'globalize'; -import 'emby-button'; +import appSettings from '../../../scripts/settings/appSettings'; +import loading from '../../../components/loading/loading'; +import globalize from '../../../scripts/globalize'; +import '../../../elements/emby-button/emby-button'; /* eslint-disable indent */ @@ -51,7 +51,7 @@ import 'emby-button'; view.querySelector('.addServerForm').addEventListener('submit', onServerSubmit); view.querySelector('.btnCancel').addEventListener('click', goBack); - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(view); }); @@ -62,7 +62,7 @@ import 'emby-button'; } function goBack() { - import('appRouter').then(({default: appRouter}) => { + import('../../../components/appRouter').then(({default: appRouter}) => { appRouter.back(); }); } diff --git a/src/controllers/session/forgotPassword/index.js b/src/controllers/session/forgotPassword/index.js index 5b92e255da..02de41e344 100644 --- a/src/controllers/session/forgotPassword/index.js +++ b/src/controllers/session/forgotPassword/index.js @@ -1,4 +1,4 @@ -import globalize from 'globalize'; +import globalize from '../../../scripts/globalize'; /* eslint-disable indent */ diff --git a/src/controllers/session/login/index.js b/src/controllers/session/login/index.js index 1592e6b112..4aef28b17d 100644 --- a/src/controllers/session/login/index.js +++ b/src/controllers/session/login/index.js @@ -1,13 +1,14 @@ -import appHost from 'apphost'; -import appSettings from 'appSettings'; -import dom from 'dom'; -import loading from 'loading'; -import layoutManager from 'layoutManager'; -import libraryMenu from 'libraryMenu'; -import browser from 'browser'; -import globalize from 'globalize'; -import 'cardStyle'; -import 'emby-checkbox'; +import appHost from '../../../components/apphost'; +import appSettings from '../../../scripts/settings/appSettings'; +import dom from '../../../scripts/dom'; +import connectionManager from 'jellyfin-apiclient'; +import loading from '../../../components/loading/loading'; +import layoutManager from '../../../components/layoutManager'; +import libraryMenu from '../../../scripts/libraryMenu'; +import browser from '../../../scripts/browser'; +import globalize from '../../../scripts/globalize'; +import '../../../components/cardbuilder/card.css'; +import '../../../elements/emby-checkbox/emby-checkbox'; /* eslint-disable indent */ @@ -27,7 +28,7 @@ import 'emby-checkbox'; const UnauthorizedOrForbidden = [401, 403]; if (UnauthorizedOrForbidden.includes(response.status)) { - import('toast').then(({default: toast}) => { + import('../../../components/toast/toast').then((toast) => { const messageKey = response.status === 401 ? 'MessageInvalidUser' : 'MessageUnauthorizedUser'; toast(globalize.translate(messageKey)); }); @@ -202,7 +203,7 @@ import 'emby-checkbox'; view.querySelector('.manualLoginForm').classList.add('hide'); view.querySelector('.btnManual').classList.remove('hide'); - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(view); }); } diff --git a/src/controllers/session/resetPassword/index.js b/src/controllers/session/resetPassword/index.js index d4f7df5bbd..8ed9c18dd8 100644 --- a/src/controllers/session/resetPassword/index.js +++ b/src/controllers/session/resetPassword/index.js @@ -1,4 +1,4 @@ -import globalize from 'globalize'; +import globalize from '../../../scripts/globalize'; /* eslint-disable indent */ diff --git a/src/controllers/session/selectServer/index.js b/src/controllers/session/selectServer/index.js index 6a590fc318..721cc8c106 100644 --- a/src/controllers/session/selectServer/index.js +++ b/src/controllers/session/selectServer/index.js @@ -1,19 +1,20 @@ -import loading from 'loading'; -import appRouter from 'appRouter'; -import layoutManager from 'layoutManager'; -import libraryMenu from 'libraryMenu'; -import appSettings from 'appSettings'; -import focusManager from 'focusManager'; -import globalize from 'globalize'; -import actionSheet from 'actionsheet'; -import dom from 'dom'; -import browser from 'browser'; -import 'material-icons'; -import 'flexStyles'; -import 'emby-scroller'; -import 'emby-itemscontainer'; -import 'cardStyle'; -import 'emby-button'; +import loading from '../../../components/loading/loading'; +import appRouter from '../../../components/appRouter'; +import layoutManager from '../../../components/layoutManager'; +import libraryMenu from '../../../scripts/libraryMenu'; +import appSettings from '../../../scripts/settings/appSettings'; +import focusManager from '../../../components/focusManager'; +import connectionManager from 'jellyfin-apiclient'; +import globalize from '../../../scripts/globalize'; +import actionSheet from '../../../components/actionSheet/actionSheet'; +import dom from '../../../scripts/dom'; +import browser from '../../../scripts/browser'; +import 'material-design-icons-iconfont'; +import '../../../assets/css/flexstyles.css'; +import '../../../elements/emby-scroller/emby-scroller'; +import '../../../elements/emby-itemscontainer/emby-itemscontainer'; +import '../../../components/cardbuilder/card.css'; +import '../../../elements/emby-button/emby-button'; /* eslint-disable indent */ @@ -100,7 +101,7 @@ import 'emby-button'; } function alertTextWithOptions(options) { - import('alert').then(({default: alert}) => { + import('../../../components/alert').then(({default: alert}) => { alert(options); }); } diff --git a/src/controllers/shows/episodes.js b/src/controllers/shows/episodes.js index 6dd633d7b0..fb78c47b80 100644 --- a/src/controllers/shows/episodes.js +++ b/src/controllers/shows/episodes.js @@ -1,12 +1,12 @@ -import loading from 'loading'; -import events from 'events'; -import libraryBrowser from 'libraryBrowser'; -import imageLoader from 'imageLoader'; -import listView from 'listView'; -import cardBuilder from 'cardBuilder'; -import * as userSettings from 'userSettings'; -import globalize from 'globalize'; -import 'emby-itemscontainer'; +import loading from '../../components/loading/loading'; +import events from 'jellyfin-apiclient'; +import libraryBrowser from '../../scripts/libraryBrowser'; +import imageLoader from '../../components/images/imageLoader'; +import listView from '../../components/listview/listview'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import * as userSettings from '../../scripts/settings/userSettings'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; /* eslint-disable indent */ @@ -160,7 +160,7 @@ import 'emby-itemscontainer'; loading.hide(); isLoading = false; - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(page); }); }); @@ -171,7 +171,7 @@ import 'emby-itemscontainer'; let isLoading = false; self.showFilterMenu = function () { - import('components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { + import('../../components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { const filterDialog = new filterDialogFactory({ query: getQuery(tabContent), mode: 'episodes', diff --git a/src/controllers/shows/tvgenres.js b/src/controllers/shows/tvgenres.js index 3a17fd7997..75e89ea9c9 100644 --- a/src/controllers/shows/tvgenres.js +++ b/src/controllers/shows/tvgenres.js @@ -1,11 +1,11 @@ -import layoutManager from 'layoutManager'; -import loading from 'loading'; -import libraryBrowser from 'libraryBrowser'; -import cardBuilder from 'cardBuilder'; -import lazyLoader from 'lazyLoader'; -import globalize from 'globalize'; -import appRouter from 'appRouter'; -import 'emby-button'; +import layoutManager from '../../components/layoutManager'; +import loading from '../../components/loading/loading'; +import libraryBrowser from '../../scripts/libraryBrowser'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import lazyLoader from '../../components/lazyLoader/lazyLoaderIntersectionObserver'; +import globalize from '../../scripts/globalize'; +import appRouter from '../../components/appRouter'; +import '../../elements/emby-button/emby-button'; /* eslint-disable indent */ diff --git a/src/controllers/shows/tvrecommended.js b/src/controllers/shows/tvrecommended.js index db7bef2d50..d778beebff 100644 --- a/src/controllers/shows/tvrecommended.js +++ b/src/controllers/shows/tvrecommended.js @@ -1,17 +1,18 @@ -import events from 'events'; -import inputManager from 'inputManager'; -import libraryMenu from 'libraryMenu'; -import layoutManager from 'layoutManager'; -import loading from 'loading'; -import dom from 'dom'; -import * as userSettings from 'userSettings'; -import cardBuilder from 'cardBuilder'; -import playbackManager from 'playbackManager'; -import * as mainTabsManager from 'mainTabsManager'; -import globalize from 'globalize'; -import 'scrollStyles'; -import 'emby-itemscontainer'; -import 'emby-button'; + +import events from 'jellyfin-apiclient'; +import inputManager from '../../scripts/inputManager'; +import libraryMenu from '../../scripts/libraryMenu'; +import layoutManager from '../../components/layoutManager'; +import loading from '../../components/loading/loading'; +import dom from '../../scripts/dom'; +import * as userSettings from '../../scripts/settings/userSettings'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import playbackManager from '../../components/playback/playbackmanager'; +import * as mainTabsManager from '../../components/maintabsmanager'; +import globalize from '../../scripts/globalize'; +import '../../assets/css/scrollstyles.css'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; +import '../../elements/emby-button/emby-button'; /* eslint-disable indent */ @@ -127,7 +128,7 @@ import 'emby-button'; }); loading.hide(); - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(view); }); }); diff --git a/src/controllers/shows/tvshows.js b/src/controllers/shows/tvshows.js index 949c994606..b59e5a2c4d 100644 --- a/src/controllers/shows/tvshows.js +++ b/src/controllers/shows/tvshows.js @@ -1,13 +1,13 @@ -import loading from 'loading'; -import events from 'events'; -import libraryBrowser from 'libraryBrowser'; -import imageLoader from 'imageLoader'; -import listView from 'listView'; -import cardBuilder from 'cardBuilder'; -import AlphaPicker from 'alphaPicker'; -import * as userSettings from 'userSettings'; -import globalize from 'globalize'; -import 'emby-itemscontainer'; +import loading from '../../components/loading/loading'; +import events from 'jellyfin-apiclient'; +import libraryBrowser from '../../scripts/libraryBrowser'; +import imageLoader from '../../components/images/imageLoader'; +import listView from '../../components/listview/listview'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import AlphaPicker from '../../components/alphaPicker/alphaPicker'; +import * as userSettings from '../../scripts/settings/userSettings'; +import globalize from '../../scripts/globalize'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; /* eslint-disable indent */ @@ -190,7 +190,7 @@ import 'emby-itemscontainer'; loading.hide(); isLoading = false; - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(page); }); }); @@ -214,7 +214,7 @@ import 'emby-itemscontainer'; let isLoading = false; this.showFilterMenu = function () { - import('components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { + import('../../components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { const filterDialog = new filterDialogFactory({ query: getQuery(tabContent), mode: 'series', diff --git a/src/controllers/shows/tvstudios.js b/src/controllers/shows/tvstudios.js index 4be717fb7f..5a0276e5f4 100644 --- a/src/controllers/shows/tvstudios.js +++ b/src/controllers/shows/tvstudios.js @@ -1,6 +1,6 @@ -import loading from 'loading'; -import libraryBrowser from 'libraryBrowser'; -import cardBuilder from 'cardBuilder'; +import loading from '../../components/loading/loading'; +import libraryBrowser from '../../scripts/libraryBrowser'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; /* eslint-disable indent */ @@ -50,7 +50,7 @@ import cardBuilder from 'cardBuilder'; }); loading.hide(); - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(context); }); }); diff --git a/src/controllers/shows/tvupcoming.js b/src/controllers/shows/tvupcoming.js index f9df3df343..897c02b5a8 100644 --- a/src/controllers/shows/tvupcoming.js +++ b/src/controllers/shows/tvupcoming.js @@ -1,11 +1,11 @@ -import layoutManager from 'layoutManager'; -import loading from 'loading'; -import datetime from 'datetime'; -import cardBuilder from 'cardBuilder'; -import imageLoader from 'imageLoader'; -import globalize from 'globalize'; -import 'scrollStyles'; -import 'emby-itemscontainer'; +import layoutManager from '../../components/layoutManager'; +import loading from '../../components/loading/loading'; +import datetime from '../../scripts/datetime'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import imageLoader from '../../components/images/imageLoader'; +import globalize from '../../scripts/globalize'; +import '../../assets/css/scrollstyles.css'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; /* eslint-disable indent */ diff --git a/src/controllers/user/display/index.js b/src/controllers/user/display/index.js index 54f71ad571..322da73772 100644 --- a/src/controllers/user/display/index.js +++ b/src/controllers/user/display/index.js @@ -1,6 +1,6 @@ -import DisplaySettings from 'displaySettings'; -import * as userSettings from 'userSettings'; -import autoFocuser from 'autoFocuser'; +import DisplaySettings from '../../../components/displaySettings/displaySettings'; +import * as userSettings from '../../../scripts/settings/userSettings'; +import autoFocuser from '../../../components/autoFocuser'; /* eslint-disable indent */ diff --git a/src/controllers/user/home/index.js b/src/controllers/user/home/index.js index 539365ff97..a1bb503adb 100644 --- a/src/controllers/user/home/index.js +++ b/src/controllers/user/home/index.js @@ -1,7 +1,7 @@ -import HomescreenSettings from 'homescreenSettings'; -import * as userSettings from 'userSettings'; -import autoFocuser from 'autoFocuser'; -import 'listViewStyle'; +import HomescreenSettings from '../../../components/homeScreenSettings/homeScreenSettings'; +import * as userSettings from '../../../scripts/settings/userSettings'; +import autoFocuser from '../../../components/autoFocuser'; +import '../../../components/listview/listview.css'; /* eslint-disable indent */ diff --git a/src/controllers/user/menu/index.js b/src/controllers/user/menu/index.js index 88cf28a216..e480d02588 100644 --- a/src/controllers/user/menu/index.js +++ b/src/controllers/user/menu/index.js @@ -1,7 +1,7 @@ -import appHost from 'apphost'; -import layoutManager from 'layoutManager'; -import 'listViewStyle'; -import 'emby-button'; +import appHost from '../../../components/apphost'; +import '../../../components/listview/listview.css'; +import '../../../elements/emby-button/emby-button'; +import layoutManager from '../../../components/layoutManager'; export default function (view, params) { view.querySelector('.btnLogout').addEventListener('click', function () { @@ -53,7 +53,7 @@ export default function (view, params) { page.querySelector('.adminSection').classList.add('hide'); } - import('autoFocuser').then(({default: autoFocuser}) => { + import('../../../components/autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(view); }); }); diff --git a/src/controllers/user/playback/index.js b/src/controllers/user/playback/index.js index 34a5ae0b1d..a44e96ec10 100644 --- a/src/controllers/user/playback/index.js +++ b/src/controllers/user/playback/index.js @@ -1,7 +1,8 @@ -import PlaybackSettings from 'playbackSettings'; -import * as userSettings from 'userSettings'; -import autoFocuser from 'autoFocuser'; -import 'listViewStyle'; + +import PlaybackSettings from '../../../components/playbackSettings/playbackSettings'; +import * as userSettings from '../../../scripts/settings/userSettings'; +import autoFocuser from '../../../components/autoFocuser'; +import '../../../components/listview/listview.css'; /* eslint-disable indent */ diff --git a/src/controllers/user/profile/index.js b/src/controllers/user/profile/index.js index 631253d019..deedaf306c 100644 --- a/src/controllers/user/profile/index.js +++ b/src/controllers/user/profile/index.js @@ -1,9 +1,9 @@ -import UserPasswordPage from 'controllers/dashboard/users/userpasswordpage'; -import loading from 'loading'; -import libraryMenu from 'libraryMenu'; -import appHost from 'apphost'; -import globalize from 'globalize'; -import 'emby-button'; +import UserPasswordPage from '../../dashboard/users/userpasswordpage'; +import loading from '../../../components/loading/loading'; +import libraryMenu from '../../../scripts/libraryMenu'; +import appHost from '../../../components/apphost'; +import globalize from '../../../scripts/globalize'; +import '../../../elements/emby-button/emby-button'; function reloadUser(page) { const userId = getParameterByName('userId'); @@ -40,7 +40,7 @@ function onFileReaderError(evt) { loading.hide(); switch (evt.target.error.code) { case evt.target.error.NOT_FOUND_ERR: - import('toast').then(({default: toast}) => { + import('../../../components/toast/toast').then((toast) => { toast(globalize.translate('FileNotFound')); }); break; @@ -49,7 +49,7 @@ function onFileReaderError(evt) { break; case evt.target.error.NOT_READABLE_ERR: default: - import('toast').then(({default: toast}) => { + import('../../../components/toast/toast').then((toast) => { toast(globalize.translate('FileReadError')); }); } @@ -57,7 +57,7 @@ function onFileReaderError(evt) { function onFileReaderAbort(evt) { loading.hide(); - import('toast').then(({default: toast}) => { + import('../../../components/toast/toast').then((toast) => { toast(globalize.translate('FileReadCancelled')); }); } @@ -89,7 +89,7 @@ export default function (view, params) { reloadUser(view); new UserPasswordPage(view, params); view.querySelector('#btnDeleteImage').addEventListener('click', function () { - import('confirm').then(({default: confirm}) => { + import('../../../components/confirm/confirm').then(({default: confirm}) => { confirm(globalize.translate('DeleteImageConfirmation'), globalize.translate('DeleteImage')).then(function () { loading.show(); const userId = getParameterByName('userId'); diff --git a/src/controllers/user/subtitles/index.js b/src/controllers/user/subtitles/index.js index efa2f1bead..deb86535df 100644 --- a/src/controllers/user/subtitles/index.js +++ b/src/controllers/user/subtitles/index.js @@ -1,6 +1,6 @@ -import SubtitleSettings from 'subtitleSettings'; -import * as userSettings from 'userSettings'; -import autoFocuser from 'autoFocuser'; +import SubtitleSettings from '../../../components/subtitlesettings/subtitlesettings'; +import * as userSettings from '../../../scripts/settings/userSettings'; +import autoFocuser from '../../../components/autoFocuser'; /* eslint-disable indent */ diff --git a/src/controllers/wizard/finish/index.js b/src/controllers/wizard/finish/index.js index 5451d6665c..446d01e61c 100644 --- a/src/controllers/wizard/finish/index.js +++ b/src/controllers/wizard/finish/index.js @@ -1,4 +1,4 @@ -import loading from 'loading'; +import loading from '../../../components/loading/loading'; function onFinish() { loading.show(); diff --git a/src/controllers/wizard/remote/index.js b/src/controllers/wizard/remote/index.js index b967d668ad..8f0aff72f3 100644 --- a/src/controllers/wizard/remote/index.js +++ b/src/controllers/wizard/remote/index.js @@ -1,7 +1,7 @@ -import loading from 'loading'; -import 'emby-checkbox'; -import 'emby-button'; -import 'emby-select'; +import loading from '../../../components/loading/loading'; +import '../../../elements/emby-checkbox/emby-checkbox'; +import '../../../elements/emby-button/emby-button'; +import '../../../elements/emby-select/emby-select'; function save(page) { loading.show(); diff --git a/src/controllers/wizard/settings/index.js b/src/controllers/wizard/settings/index.js index 6e3a82cd9b..87cae05275 100644 --- a/src/controllers/wizard/settings/index.js +++ b/src/controllers/wizard/settings/index.js @@ -1,7 +1,7 @@ -import loading from 'loading'; -import 'emby-checkbox'; -import 'emby-button'; -import 'emby-select'; +import loading from '../../../components/loading/loading'; +import '../../../elements/emby-checkbox/emby-checkbox'; +import '../../../elements/emby-button/emby-button'; +import '../../../elements/emby-select/emby-select'; function save(page) { loading.show(); diff --git a/src/controllers/wizard/start/index.js b/src/controllers/wizard/start/index.js index 3cd53b4ceb..54e3d8e7df 100644 --- a/src/controllers/wizard/start/index.js +++ b/src/controllers/wizard/start/index.js @@ -1,7 +1,7 @@ -import $ from 'jQuery'; -import loading from 'loading'; -import 'emby-button'; -import 'emby-select'; +import 'jquery'; +import loading from '../../../components/loading/loading'; +import '../../../elements/emby-button/emby-button'; +import '../../../elements/emby-select/emby-select'; function loadPage(page, config, languageOptions) { $('#selectLocalizationLanguage', page).html(languageOptions.map(function (l) { diff --git a/src/controllers/wizard/user/index.js b/src/controllers/wizard/user/index.js index ec587fec8e..75cfde5b9b 100644 --- a/src/controllers/wizard/user/index.js +++ b/src/controllers/wizard/user/index.js @@ -1,8 +1,8 @@ -import loading from 'loading'; -import globalize from 'globalize'; -import 'dashboardcss'; -import 'emby-input'; -import 'emby-button'; +import loading from '../../../components/loading/loading'; +import globalize from '../../../scripts/globalize'; +import '../../../assets/css/dashboard.css'; +import '../../../elements/emby-input/emby-input'; +import '../../../elements/emby-button/emby-button'; function getApiClient() { return ApiClient; @@ -36,7 +36,7 @@ function onSubmit(e) { const form = this; if (form.querySelector('#txtManualPassword').value != form.querySelector('#txtPasswordConfirm').value) { - import('toast').then(({default: toast}) => { + import('../../../components/toast/toast').then((toast) => { toast(globalize.translate('PasswordMatchError')); }); } else { diff --git a/src/elements/emby-button/emby-button.js b/src/elements/emby-button/emby-button.js index 213bbc8e7f..9eefbcbed4 100644 --- a/src/elements/emby-button/emby-button.js +++ b/src/elements/emby-button/emby-button.js @@ -1,10 +1,9 @@ -import dom from 'dom'; -import layoutManager from 'layoutManager'; -import shell from 'shell'; -import appRouter from 'appRouter'; -import appHost from 'apphost'; -import 'css!./emby-button'; -import 'webcomponents'; +import { removeEventListener, addEventListener } from '../../scripts/dom'; +import layoutManager from '../../components/layoutManager'; +import shell from '../../scripts/shell'; +import appRouter from '../../components/appRouter'; +import appHost from '../../components/apphost'; +import './emby-button.css'; const EmbyButtonPrototype = Object.create(HTMLButtonElement.prototype); const EmbyLinkButtonPrototype = Object.create(HTMLAnchorElement.prototype); @@ -30,7 +29,7 @@ EmbyButtonPrototype.createdCallback = function () { return; } - this.classList.add('emby-button'); + this.classList.add('../../elements/emby-button/emby-button'); // TODO replace all instances of element-showfocus with this method if (layoutManager.tv) { // handles all special css for tv layout @@ -41,8 +40,8 @@ EmbyButtonPrototype.createdCallback = function () { EmbyButtonPrototype.attachedCallback = function () { if (this.tagName === 'A') { - dom.removeEventListener(this, 'click', onAnchorClick, {}); - dom.addEventListener(this, 'click', onAnchorClick, {}); + removeEventListener(this, 'click', onAnchorClick, {}); + addEventListener(this, 'click', onAnchorClick, {}); if (this.getAttribute('data-autohide') === 'true') { if (appHost.supports('externallinks')) { @@ -55,13 +54,13 @@ EmbyButtonPrototype.attachedCallback = function () { }; EmbyButtonPrototype.detachedCallback = function () { - dom.removeEventListener(this, 'click', onAnchorClick, {}); + removeEventListener(this, 'click', onAnchorClick, {}); }; EmbyLinkButtonPrototype.createdCallback = EmbyButtonPrototype.createdCallback; EmbyLinkButtonPrototype.attachedCallback = EmbyButtonPrototype.attachedCallback; -document.registerElement('emby-button', { +document.registerElement('../../elements/emby-button/emby-button', { prototype: EmbyButtonPrototype, extends: 'button' }); diff --git a/src/elements/emby-button/paper-icon-button-light.js b/src/elements/emby-button/paper-icon-button-light.js index f6c754fedb..4ecfb5b7c3 100644 --- a/src/elements/emby-button/paper-icon-button-light.js +++ b/src/elements/emby-button/paper-icon-button-light.js @@ -1,18 +1,18 @@ -import layoutManager from 'layoutManager'; -import 'css!./emby-button'; -import 'webcomponents'; +import layoutManager from '../../components/layoutManager'; +import './emby-button.css'; +import 'webcomponents.js'; const EmbyButtonPrototype = Object.create(HTMLButtonElement.prototype); EmbyButtonPrototype.createdCallback = function () { - this.classList.add('paper-icon-button-light'); + this.classList.add('../../elements/emby-button/paper-icon-button-light'); if (layoutManager.tv) { this.classList.add('show-focus'); } }; -document.registerElement('paper-icon-button-light', { +document.registerElement('../../elements/emby-button/paper-icon-button-light', { prototype: EmbyButtonPrototype, extends: 'button' }); diff --git a/src/elements/emby-checkbox/emby-checkbox.js b/src/elements/emby-checkbox/emby-checkbox.js index d44c58ed48..a03b238436 100644 --- a/src/elements/emby-checkbox/emby-checkbox.js +++ b/src/elements/emby-checkbox/emby-checkbox.js @@ -1,7 +1,7 @@ -import browser from 'browser'; -import dom from 'dom'; -import 'css!./emby-checkbox'; -import 'webcomponents'; +import browser from '../../scripts/browser'; +import dom from '../../scripts/dom'; +import './emby-checkbox.css'; +import 'webcomponents.js'; /* eslint-disable indent */ diff --git a/src/elements/emby-collapse/emby-collapse.js b/src/elements/emby-collapse/emby-collapse.js index c87e73d48f..711e679205 100644 --- a/src/elements/emby-collapse/emby-collapse.js +++ b/src/elements/emby-collapse/emby-collapse.js @@ -1,6 +1,6 @@ -import 'css!./emby-collapse'; -import 'webcomponents'; -import 'emby-button'; +import './emby-collapse'; +import 'webcomponents.js'; +import '../../elements/emby-button/emby-button'; /* eslint-disable indent */ diff --git a/src/elements/emby-input/emby-input.js b/src/elements/emby-input/emby-input.js index 3a71e29a6f..713559bca0 100644 --- a/src/elements/emby-input/emby-input.js +++ b/src/elements/emby-input/emby-input.js @@ -1,7 +1,7 @@ -import browser from 'browser'; -import dom from 'dom'; -import 'css!./emby-input'; -import 'webcomponents'; +import browser from '../../scripts/browser'; +import dom from '../../scripts/dom'; +import './emby-input.css'; +import 'webcomponents.js'; /* eslint-disable indent */ diff --git a/src/elements/emby-itemrefreshindicator/emby-itemrefreshindicator.js b/src/elements/emby-itemrefreshindicator/emby-itemrefreshindicator.js index 51f3fc5be9..0fd9eeb952 100644 --- a/src/elements/emby-itemrefreshindicator/emby-itemrefreshindicator.js +++ b/src/elements/emby-itemrefreshindicator/emby-itemrefreshindicator.js @@ -1,8 +1,8 @@ -import EmbyProgressRing from 'emby-progressring'; -import dom from 'dom'; -import serverNotifications from 'serverNotifications'; -import events from 'events'; -import 'webcomponents'; +import EmbyProgressRing from '../emby-progressring/emby-progressring'; +import dom from '../../scripts/dom'; +import serverNotifications from '../../scripts/serverNotifications'; +import events from 'jellyfin-apiclient'; +import 'webcomponents.js'; /* eslint-disable indent */ diff --git a/src/elements/emby-itemscontainer/emby-itemscontainer.js b/src/elements/emby-itemscontainer/emby-itemscontainer.js index 7d8f941603..1f8b1607a1 100644 --- a/src/elements/emby-itemscontainer/emby-itemscontainer.js +++ b/src/elements/emby-itemscontainer/emby-itemscontainer.js @@ -1,15 +1,17 @@ -import itemShortcuts from 'itemShortcuts'; -import inputManager from 'inputManager'; -import playbackManager from 'playbackManager'; -import imageLoader from 'imageLoader'; -import layoutManager from 'layoutManager'; -import browser from 'browser'; -import dom from 'dom'; -import loading from 'loading'; -import focusManager from 'focusManager'; -import serverNotifications from 'serverNotifications'; -import events from 'events'; -import 'webcomponents'; + +import itemShortcuts from '../../components/shortcuts'; +import inputManager from '../../scripts/inputManager'; +import connectionManager from 'jellyfin-apiclient'; +import playbackManager from '../../components/playback/playbackmanager'; +import imageLoader from '../../components/images/imageLoader'; +import layoutManager from '../../components/layoutManager'; +import browser from '../../scripts/browser'; +import dom from '../../scripts/dom'; +import loading from '../../components/loading/loading'; +import focusManager from '../../components/focusManager'; +import serverNotifications from '../../scripts/serverNotifications'; +import events from 'jellyfin-apiclient'; +import 'webcomponents.js'; /* eslint-disable indent */ @@ -72,7 +74,7 @@ import 'webcomponents'; } const self = this; - import('multiSelect').then(({default: MultiSelect}) => { + import('../../components/multiSelect/multiSelect').then((MultiSelect) => { self.multiSelect = new MultiSelect({ container: self, bindOnClick: false @@ -132,7 +134,7 @@ import 'webcomponents'; } const self = this; - import('sortable').then(({default: Sortable}) => { + import('sortablejs').then((Sortable) => { self.sortable = new Sortable(self, { draggable: '.listItem', handle: '.listViewDragHandle', @@ -148,7 +150,7 @@ import 'webcomponents'; function onUserDataChanged(e, apiClient, userData) { const itemsContainer = this; - import('cardBuilder').then(({default: cardBuilder}) => { + import('../../components/cardbuilder/cardBuilder').then((cardBuilder) => { cardBuilder.onUserDataChanged(userData, itemsContainer); }); @@ -183,7 +185,7 @@ import 'webcomponents'; // This could be null, not supported by all tv providers const newTimerId = data.Id; - import('cardBuilder').then(({default: cardBuilder}) => { + import('../../components/cardbuilder/cardBuilder').then((cardBuilder) => { cardBuilder.onTimerCreated(programId, newTimerId, itemsContainer); }); } @@ -203,7 +205,7 @@ import 'webcomponents'; return; } - import('cardBuilder').then(({default: cardBuilder}) => { + import('../../components/cardbuilder/cardBuilder').then((cardBuilder) => { cardBuilder.onTimerCancelled(data.Id, itemsContainer); }); } @@ -215,7 +217,7 @@ import 'webcomponents'; return; } - import('cardBuilder').then(({default: cardBuilder}) => { + import('../../components/cardbuilder/cardBuilder').then((cardBuilder) => { cardBuilder.onSeriesTimerCancelled(data.Id, itemsContainer); }); } @@ -482,7 +484,7 @@ import 'webcomponents'; focusManager.autoFocus(itemsContainer); } - document.registerElement('emby-itemscontainer', { + document.registerElement('../../elements/emby-itemscontainer/emby-itemscontainer', { prototype: ItemsContainerPrototype, extends: 'div' }); diff --git a/src/elements/emby-playstatebutton/emby-playstatebutton.js b/src/elements/emby-playstatebutton/emby-playstatebutton.js index 8d17ddf9ff..26a5c82807 100644 --- a/src/elements/emby-playstatebutton/emby-playstatebutton.js +++ b/src/elements/emby-playstatebutton/emby-playstatebutton.js @@ -1,7 +1,8 @@ -import serverNotifications from 'serverNotifications'; -import events from 'events'; -import globalize from 'globalize'; -import EmbyButtonPrototype from 'emby-button'; +import connectionManager from 'jellyfin-apiclient'; +import serverNotifications from '../../scripts/serverNotifications'; +import events from 'jellyfin-apiclient'; +import globalize from '../../scripts/globalize'; +import EmbyButtonPrototype from '../../elements/emby-button/emby-button'; /* eslint-disable indent */ diff --git a/src/elements/emby-progressring/emby-progressring.js b/src/elements/emby-progressring/emby-progressring.js index 63b9f73f10..83b49b7bae 100644 --- a/src/elements/emby-progressring/emby-progressring.js +++ b/src/elements/emby-progressring/emby-progressring.js @@ -1,5 +1,5 @@ -import 'css!./emby-progressring'; -import 'webcomponents'; +import './emby-progressring'; +import 'webcomponents.js'; /* eslint-disable indent */ @@ -9,7 +9,7 @@ import 'webcomponents'; this.classList.add('progressring'); const instance = this; - import('text!./emby-progressring.template.html').then(({default: template}) => { + import('./emby-progressring.template.html').then(({default: template}) => { instance.innerHTML = template; if (window.MutationObserver) { diff --git a/src/elements/emby-radio/emby-radio.js b/src/elements/emby-radio/emby-radio.js index 7c468a84a6..f2b7fdf81c 100644 --- a/src/elements/emby-radio/emby-radio.js +++ b/src/elements/emby-radio/emby-radio.js @@ -1,7 +1,7 @@ -import layoutManager from 'layoutManager'; -import 'css!./emby-radio'; -import 'webcomponents'; -import browser from 'browser'; +import layoutManager from '../../components/layoutManager'; +import browser from '../../scripts/browser'; +import 'webcomponents.js'; +import './emby-radio.css'; /* eslint-disable indent */ diff --git a/src/elements/emby-ratingbutton/emby-ratingbutton.js b/src/elements/emby-ratingbutton/emby-ratingbutton.js index 865d918b45..42f7be68f7 100644 --- a/src/elements/emby-ratingbutton/emby-ratingbutton.js +++ b/src/elements/emby-ratingbutton/emby-ratingbutton.js @@ -1,7 +1,8 @@ -import serverNotifications from 'serverNotifications'; -import events from 'events'; -import globalize from 'globalize'; -import EmbyButtonPrototype from 'emby-button'; +import connectionManager from 'jellyfin-apiclient'; +import serverNotifications from '../../scripts/serverNotifications'; +import events from 'jellyfin-apiclient'; +import globalize from '../../scripts/globalize'; +import EmbyButtonPrototype from '../emby-button/emby-button'; /* eslint-disable indent */ diff --git a/src/elements/emby-scrollbuttons/emby-scrollbuttons.js b/src/elements/emby-scrollbuttons/emby-scrollbuttons.js index f7665c0618..ad4f591067 100644 --- a/src/elements/emby-scrollbuttons/emby-scrollbuttons.js +++ b/src/elements/emby-scrollbuttons/emby-scrollbuttons.js @@ -1,6 +1,6 @@ -import 'css!./emby-scrollbuttons'; -import 'webcomponents'; -import 'paper-icon-button-light'; +import './emby-scrollbuttons'; +import 'webcomponents.js'; +import '../../elements/emby-button/paper-icon-button-light'; /* eslint-disable indent */ diff --git a/src/elements/emby-scroller/emby-scroller.js b/src/elements/emby-scroller/emby-scroller.js index d7133e317a..9bdbc6c8e1 100644 --- a/src/elements/emby-scroller/emby-scroller.js +++ b/src/elements/emby-scroller/emby-scroller.js @@ -1,18 +1,18 @@ -import scroller from 'scroller'; -import dom from 'dom'; -import layoutManager from 'layoutManager'; -import inputManager from 'inputManager'; -import focusManager from 'focusManager'; -import browser from 'browser'; -import 'webcomponents'; -import 'css!./emby-scroller'; +import scroller from '../../libraries/scroller'; +import dom from '../../scripts/dom'; +import layoutManager from '../../components/layoutManager'; +import inputManager from '../../scripts/inputManager'; +import focusManager from '../../components/focusManager'; +import browser from '../../scripts/browser'; +import 'webcomponents.js'; +import './emby-scroller.css'; /* eslint-disable indent */ const ScrollerPrototype = Object.create(HTMLDivElement.prototype); ScrollerPrototype.createdCallback = function () { - this.classList.add('emby-scroller'); + this.classList.add('../../elements/emby-scroller/emby-scroller'); }; function initCenterFocus(elem, scrollerInstance) { @@ -156,7 +156,7 @@ import 'css!./emby-scroller'; }; function loadScrollButtons(scroller) { - import('emby-scrollbuttons').then(() => { + import('../emby-scrollbuttons/emby-scrollbuttons').then(() => { scroller.insertAdjacentHTML('beforebegin', '
'); }); } @@ -193,7 +193,7 @@ import 'css!./emby-scroller'; } }; - document.registerElement('emby-scroller', { + document.registerElement('../../elements/emby-scroller/emby-scroller', { prototype: ScrollerPrototype, extends: 'div' }); diff --git a/src/elements/emby-select/emby-select.js b/src/elements/emby-select/emby-select.js index 0629a74e52..b75045b8dd 100644 --- a/src/elements/emby-select/emby-select.js +++ b/src/elements/emby-select/emby-select.js @@ -1,8 +1,9 @@ -import layoutManager from 'layoutManager'; -import browser from 'browser'; -import actionsheet from 'actionsheet'; -import 'css!./emby-select'; -import 'webcomponents'; + +import layoutManager from '../../components/layoutManager'; +import browser from '../../scripts/browser'; +import actionsheet from '../../components/actionSheet/actionSheet'; +import './emby-select.css'; +import 'webcomponents.js'; /* eslint-disable indent */ diff --git a/src/elements/emby-slider/emby-slider.js b/src/elements/emby-slider/emby-slider.js index 555394af0d..943fbeeeb5 100644 --- a/src/elements/emby-slider/emby-slider.js +++ b/src/elements/emby-slider/emby-slider.js @@ -1,10 +1,10 @@ -import browser from 'browser'; -import dom from 'dom'; -import layoutManager from 'layoutManager'; -import keyboardnavigation from 'keyboardnavigation'; -import 'css!./emby-slider'; -import 'webcomponents'; -import 'emby-input'; +import browser from '../../scripts/browser'; +import dom from '../../scripts/dom'; +import layoutManager from '../../components/layoutManager'; +import keyboardnavigation from '../../scripts/keyboardNavigation'; +import './emby-slider.css'; +import 'webcomponents.js'; +import '../emby-input/emby-input'; /* eslint-disable indent */ diff --git a/src/elements/emby-tabs/emby-tabs.js b/src/elements/emby-tabs/emby-tabs.js index 7e16e31dd4..e34d30d47a 100644 --- a/src/elements/emby-tabs/emby-tabs.js +++ b/src/elements/emby-tabs/emby-tabs.js @@ -1,10 +1,10 @@ -import dom from 'dom'; -import scroller from 'scroller'; -import browser from 'browser'; -import focusManager from 'focusManager'; -import 'webcomponents'; -import 'css!./emby-tabs'; -import 'scrollStyles'; +import dom from '../../scripts/dom'; +import scroller from '../../libraries/scroller'; +import browser from '../../scripts/browser'; +import focusManager from '../../components/focusManager'; +import 'webcomponents.js'; +import './emby-tabs.css'; +import '../../assets/css/scrollstyles.css'; /* eslint-disable indent */ diff --git a/src/elements/emby-textarea/emby-textarea.js b/src/elements/emby-textarea/emby-textarea.js index c14724346a..63a932b6cc 100644 --- a/src/elements/emby-textarea/emby-textarea.js +++ b/src/elements/emby-textarea/emby-textarea.js @@ -1,6 +1,6 @@ -import 'css!./emby-textarea'; -import 'webcomponents'; -import 'emby-input'; +import './emby-textarea.css'; +import 'webcomponents.js'; +import '../emby-input/emby-input'; /* eslint-disable indent */ diff --git a/src/elements/emby-toggle/emby-toggle.js b/src/elements/emby-toggle/emby-toggle.js index 5e78b38dd3..f359f25ccf 100644 --- a/src/elements/emby-toggle/emby-toggle.js +++ b/src/elements/emby-toggle/emby-toggle.js @@ -1,5 +1,5 @@ -import 'css!./emby-toggle'; -import 'webcomponents'; +import './emby-toggle'; +import 'webcomponents.js'; /* eslint-disable indent */ diff --git a/src/libraries/navdrawer/navdrawer.js b/src/libraries/navdrawer/navdrawer.js index 6dcf6783d1..4af9f56a1c 100644 --- a/src/libraries/navdrawer/navdrawer.js +++ b/src/libraries/navdrawer/navdrawer.js @@ -3,10 +3,10 @@ */ /* eslint-disable no-var */ -import browser from 'browser'; -import dom from 'dom'; -import 'css!./navdrawer'; -import 'scrollStyles'; +import browser from '../../scripts/browser'; +import dom from '../../scripts/dom'; +import './navdrawer.css'; +import '../../assets/css/scrollstyles.css'; export default function (options) { function getTouches(e) { diff --git a/src/libraries/screensavermanager.js b/src/libraries/screensavermanager.js index 68a7dda73b..93625449f2 100644 --- a/src/libraries/screensavermanager.js +++ b/src/libraries/screensavermanager.js @@ -1,8 +1,9 @@ -import events from 'events'; -import playbackManager from 'playbackManager'; -import pluginManager from 'pluginManager'; -import inputManager from 'inputManager'; -import * as userSettings from 'userSettings'; +import events from 'jellyfin-apiclient'; +import playbackManager from '../components/playback/playbackmanager'; +import pluginManager from '../components/pluginManager'; +import inputManager from '../scripts/inputManager'; +import connectionManager from 'jellyfin-apiclient'; +import * as userSettings from '../scripts/settings/userSettings'; function getMinIdleTime() { // Returns the minimum amount of idle time required before the screen saver can be displayed diff --git a/src/libraries/scroller.js b/src/libraries/scroller.js index de6469c743..f2baf51572 100644 --- a/src/libraries/scroller.js +++ b/src/libraries/scroller.js @@ -2,12 +2,12 @@ * and will be replaced soon by a Vue component. */ -import browser from 'browser'; -import layoutManager from 'layoutManager'; -import dom from 'dom'; -import focusManager from 'focusManager'; -import ResizeObserver from 'ResizeObserver'; -import 'scrollStyles'; +import browser from '../scripts/browser'; +import layoutManager from '../components/layoutManager'; +import dom from '../scripts/dom'; +import focusManager from '../components/focusManager'; +import ResizeObserver from 'resize-observer-polyfill'; +import '../assets/css/scrollstyles.css'; /** * Return type of the value. diff --git a/src/plugins/bookPlayer/plugin.js b/src/plugins/bookPlayer/plugin.js index c56777f378..60f12f2b5f 100644 --- a/src/plugins/bookPlayer/plugin.js +++ b/src/plugins/bookPlayer/plugin.js @@ -1,12 +1,12 @@ -import browser from 'browser'; -import loading from 'loading'; +import connectionManager from 'jellyfin-apiclient'; +import loading from '../../components/loading/loading'; import keyboardnavigation from 'keyboardnavigation'; import dialogHelper from 'dialogHelper'; import dom from 'dom'; -import events from 'events'; -import 'css!./style'; -import 'material-icons'; -import 'paper-icon-button-light'; +import events from 'jellyfin-apiclient'; +import './style'; +import 'material-design-icons-iconfont'; +import '../../elements/emby-button/paper-icon-button-light'; import TableOfContents from './tableOfContents'; diff --git a/src/plugins/chromecastPlayer/plugin.js b/src/plugins/chromecastPlayer/plugin.js index f61a0055af..ba09f9e209 100644 --- a/src/plugins/chromecastPlayer/plugin.js +++ b/src/plugins/chromecastPlayer/plugin.js @@ -1,8 +1,8 @@ import appSettings from 'appSettings'; -import * as userSettings from 'userSettings'; +import * as userSettings from '../../scripts/settings/userSettings'; import playbackManager from 'playbackManager'; import globalize from 'globalize'; -import events from 'events'; +import events from 'jellyfin-apiclient'; import castSenderApiLoader from 'castSenderApiLoader'; // Based on https://github.com/googlecast/CastVideos-chrome/blob/master/CastVideos.js diff --git a/src/plugins/htmlAudioPlayer/plugin.js b/src/plugins/htmlAudioPlayer/plugin.js index 6f413fac50..68380bcdb4 100644 --- a/src/plugins/htmlAudioPlayer/plugin.js +++ b/src/plugins/htmlAudioPlayer/plugin.js @@ -1,4 +1,4 @@ -import events from 'events'; +import events from 'jellyfin-apiclient'; import browser from 'browser'; import appHost from 'apphost'; import * as htmlMediaHelper from 'htmlMediaHelper'; diff --git a/src/plugins/htmlVideoPlayer/plugin.js b/src/plugins/htmlVideoPlayer/plugin.js index 32f96c8e2e..f4c7f25b70 100644 --- a/src/plugins/htmlVideoPlayer/plugin.js +++ b/src/plugins/htmlVideoPlayer/plugin.js @@ -1,7 +1,7 @@ import browser from 'browser'; -import events from 'events'; +import events from 'jellyfin-apiclient'; import appHost from 'apphost'; -import loading from 'loading'; +import loading from '../../components/loading/loading'; import dom from 'dom'; import playbackManager from 'playbackManager'; import appRouter from 'appRouter'; @@ -1282,7 +1282,7 @@ function tryRemoveElement(elem) { const dlg = document.querySelector('.videoPlayerContainer'); if (!dlg) { - return import('css!./style').then(() => { + return import('./style').then(() => { loading.show(); const dlg = document.createElement('div'); diff --git a/src/plugins/logoScreensaver/plugin.js b/src/plugins/logoScreensaver/plugin.js index 61b8f8a6d6..619c0de253 100644 --- a/src/plugins/logoScreensaver/plugin.js +++ b/src/plugins/logoScreensaver/plugin.js @@ -128,7 +128,7 @@ export default function () { } self.show = function () { - import('css!' + pluginManager.mapPath(self, 'style.css')).then(() => { + import('' + pluginManager.mapPath(self, 'style.css')).then(() => { let elem = document.querySelector('.logoScreenSaver'); if (!elem) { diff --git a/src/plugins/youtubePlayer/plugin.js b/src/plugins/youtubePlayer/plugin.js index eed75a8116..568077b0f9 100644 --- a/src/plugins/youtubePlayer/plugin.js +++ b/src/plugins/youtubePlayer/plugin.js @@ -1,7 +1,7 @@ -import events from 'events'; +import events from 'jellyfin-apiclient'; import browser from 'browser'; import appRouter from 'appRouter'; -import loading from 'loading'; +import loading from '../../components/loading/loading'; /* globals YT */ @@ -20,7 +20,7 @@ function createMediaElement(instance, options) { const dlg = document.querySelector('.youtubePlayerContainer'); if (!dlg) { - import('css!./style').then(() => { + import('./style').then(() => { loading.show(); const dlg = document.createElement('div'); diff --git a/src/scripts/alphanumericshortcuts.js b/src/scripts/alphanumericshortcuts.js index e76d5b11f6..22d2605b35 100644 --- a/src/scripts/alphanumericshortcuts.js +++ b/src/scripts/alphanumericshortcuts.js @@ -1,5 +1,5 @@ -import dom from 'dom'; -import focusManager from 'focusManager'; +import dom from './dom'; +import focusManager from '../components/focusManager'; let inputDisplayElement; let currentDisplayText = ''; diff --git a/src/scripts/autoBackdrops.js b/src/scripts/autoBackdrops.js index 051204ef18..0ecd583f45 100644 --- a/src/scripts/autoBackdrops.js +++ b/src/scripts/autoBackdrops.js @@ -1,6 +1,6 @@ -import backdrop from 'backdrop'; -import * as userSettings from 'userSettings'; -import libraryMenu from 'libraryMenu'; +import backdrop from '../components/backdrop/backdrop'; +import * as userSettings from './settings/userSettings'; +import libraryMenu from './libraryMenu'; const cache = {}; diff --git a/src/scripts/autoThemes.js b/src/scripts/autoThemes.js index 9dffda5d2e..e28353798d 100644 --- a/src/scripts/autoThemes.js +++ b/src/scripts/autoThemes.js @@ -1,7 +1,8 @@ -import * as userSettings from 'userSettings'; -import * as webSettings from 'webSettings'; -import skinManager from 'skinManager'; -import events from 'events'; +import * as userSettings from './settings/userSettings'; +import * as webSettings from './settings/webSettings'; +import skinManager from './themeManager'; +import connectionManager from 'jellyfin-apiclient'; +import events from 'jellyfin-apiclient'; // set the default theme when loading skinManager.setTheme(userSettings.theme()); diff --git a/src/scripts/autocast.js b/src/scripts/autocast.js index 8d90451268..9bed470669 100644 --- a/src/scripts/autocast.js +++ b/src/scripts/autocast.js @@ -1,5 +1,5 @@ -import events from 'events'; -import playbackManager from 'playbackManager'; +import { Events } from 'jellyfin-apiclient'; +import playbackManager from '../components/playback/playbackmanager'; export function supported() { return typeof(Storage) !== 'undefined'; @@ -43,5 +43,5 @@ function onOpen() { const apiClient = window.connectionManager.currentApiClient(); if (apiClient && supported()) { - events.on(apiClient, 'websocketopen', onOpen); + Events.on(apiClient, 'websocketopen', onOpen); } diff --git a/src/scripts/clientUtils.js b/src/scripts/clientUtils.js index 73801867c0..9f15197325 100644 --- a/src/scripts/clientUtils.js +++ b/src/scripts/clientUtils.js @@ -1,4 +1,3 @@ - export function getCurrentUser() { return window.ApiClient.getCurrentUser(false); } @@ -78,7 +77,7 @@ export function navigate(url, preserveQueryString) { } return new Promise(function (resolve, reject) { - import('appRouter').then(({default: appRouter}) => { + import('../components/appRouter').then((appRouter) => { return appRouter.show(url).then(resolve, reject); }); }); @@ -86,28 +85,28 @@ export function navigate(url, preserveQueryString) { export function processPluginConfigurationUpdateResult() { Promise.all([ - import('loading'), - import('toast') + import('../components/loading/loading'), + import('../components/toast/toast') ]) - .then(([{default: loading}, {default: toast}]) => { + .then(([loading, toast]) => { loading.hide(); - toast(Globalize.translate('SettingsSaved')); + toast(Globalize.translate('MessageSettingsSaved')); }); } export function processServerConfigurationUpdateResult(result) { Promise.all([ - import('loading'), - import('toast') + import('../components/loading/loading'), + import('../components/toast/toast') ]) - .then(([{default: loading}, {default: toast}]) => { + .then(([loading, toast]) => { loading.hide(); - toast(Globalize.translate('SettingsSaved')); + toast.default(Globalize.translate('MessageSettingsSaved')); }); } export function processErrorResponse(response) { - import('loading').then(({default: loading}) => { + import('../components/loading/loading').then((loading) => { loading.hide(); }); @@ -125,15 +124,15 @@ export function processErrorResponse(response) { export function alert(options) { if (typeof options == 'string') { - return void import('toast').then(({default: toast}) => { - toast({ + return void import('../components/toast/toast').then((toast) => { + toast.default({ text: options }); }); } - import('alert').then(({default: alert}) => { - alert({ + import('../components/alert').then((alert) => { + alert.default({ title: options.title || Globalize.translate('HeaderAlert'), text: options.message }).then(options.callback || function () {}); @@ -147,7 +146,8 @@ export function capabilities(appHost) { SupportsPersistentIdentifier: window.appMode === 'cordova' || window.appMode === 'android', SupportsMediaControl: true }; - return Object.assign(capabilities, appHost.getPushTokenInfo()); + appHost.getPushTokenInfo(); + return capabilities = Object.assign(capabilities, appHost.getPushTokenInfo()); } export function selectServer() { @@ -159,19 +159,19 @@ export function selectServer() { } export function hideLoadingMsg() { - import('loading').then(({default: loading}) => { + import('../components/loading/loading').then(({default: loading}) => { loading.hide(); }); } export function showLoadingMsg() { - import('loading').then(({default: loading}) => { + import('../components/loading/loading').then(({default: loading}) => { loading.show(); }); } export function confirm(message, title, callback) { - import('confirm').then(({default: confirm}) => { + import('../components/confirm/confirm').then((confirm) => { confirm(message, title).then(function() { callback(!0); }).catch(function() { diff --git a/src/scripts/datetime.js b/src/scripts/datetime.js index c6baa28ed3..34171cb4d3 100644 --- a/src/scripts/datetime.js +++ b/src/scripts/datetime.js @@ -1,4 +1,4 @@ -import globalize from 'globalize'; +import globalize from './globalize'; /* eslint-disable indent */ diff --git a/src/scripts/deleteHelper.js b/src/scripts/deleteHelper.js index a18d951e60..d20ec362d7 100644 --- a/src/scripts/deleteHelper.js +++ b/src/scripts/deleteHelper.js @@ -1,10 +1,12 @@ -import confirm from 'confirm'; -import appRouter from 'appRouter'; -import globalize from 'globalize'; + +import connectionManager from 'jellyfin-apiclient'; +import confirm from '../components/confirm/confirm'; +import appRouter from '../components/appRouter'; +import globalize from './globalize'; function alertText(options) { return new Promise(function (resolve, reject) { - import('alert').then(({default: alert}) => { + import('../components/alert').then((alert) => { alert(options).then(resolve, resolve); }); }); diff --git a/src/scripts/dfnshelper.js b/src/scripts/dfnshelper.js index 6ad2ee9709..116ba41674 100644 --- a/src/scripts/dfnshelper.js +++ b/src/scripts/dfnshelper.js @@ -1,6 +1,6 @@ import { ar, be, bg, ca, cs, da, de, el, enGB, enUS, es, faIR, fi, fr, frCA, he, hi, hr, hu, id, it, ja, kk, ko, lt, ms, nb, nl, pl, ptBR, pt, ro, ru, sk, sl, sv, tr, uk, vi, zhCN, zhTW } from 'date-fns/locale'; -import globalize from 'globalize'; +import globalize from './globalize'; const dateLocales = (locale) => ({ 'ar': ar, diff --git a/src/scripts/editorsidebar.js b/src/scripts/editorsidebar.js index 3711520f02..ab9f5864b4 100644 --- a/src/scripts/editorsidebar.js +++ b/src/scripts/editorsidebar.js @@ -1,6 +1,6 @@ -import $ from 'jQuery'; -import globalize from 'globalize'; -import 'material-icons'; +import 'jquery'; +import globalize from './globalize'; +import 'material-design-icons-iconfont'; /* eslint-disable indent */ @@ -303,7 +303,7 @@ import 'material-icons'; updateEditorNode(this, item); }).on('pagebeforeshow', '.metadataEditorPage', function () { /* eslint-disable-next-line @babel/no-unused-expressions */ - import('css!assets/css/metadataeditor.css'); + import('../assets/css/metadataeditor.css'); }).on('pagebeforeshow', '.metadataEditorPage', function () { const page = this; Dashboard.getCurrentUser().then(function (user) { diff --git a/src/scripts/fileDownloader.js b/src/scripts/fileDownloader.js index c99a6c3e35..24f1631017 100644 --- a/src/scripts/fileDownloader.js +++ b/src/scripts/fileDownloader.js @@ -1,5 +1,5 @@ -import multiDownload from 'multi-download'; -import shell from 'shell'; +import multiDownload from './multiDownload'; +import shell from './shell'; export function download(items) { if (!shell.downloadFiles(items)) { diff --git a/src/scripts/globalize.js b/src/scripts/globalize.js index d237fdcce0..a3cbb8cd2c 100644 --- a/src/scripts/globalize.js +++ b/src/scripts/globalize.js @@ -1,5 +1,5 @@ -import * as userSettings from 'userSettings'; -import events from 'events'; +import * as userSettings from './settings/userSettings'; +import events from 'jellyfin-apiclient'; /* eslint-disable indent */ diff --git a/src/scripts/inputManager.js b/src/scripts/inputManager.js index baa3deb0aa..4f98c6974a 100644 --- a/src/scripts/inputManager.js +++ b/src/scripts/inputManager.js @@ -1,8 +1,8 @@ -import playbackManager from 'playbackManager'; -import focusManager from 'focusManager'; -import appRouter from 'appRouter'; -import dom from 'dom'; -import appHost from 'apphost'; +import playbackManager from '../components/playback/playbackmanager'; +import focusManager from '../components/focusManager'; +import appRouter from '../components/appRouter'; +import dom from './dom'; +import appHost from '../components/apphost'; /* eslint-disable indent */ diff --git a/src/scripts/itembynamedetailpage.js b/src/scripts/itembynamedetailpage.js index e309267230..186cc3f70d 100644 --- a/src/scripts/itembynamedetailpage.js +++ b/src/scripts/itembynamedetailpage.js @@ -1,9 +1,10 @@ -import listView from 'listView'; -import cardBuilder from 'cardBuilder'; -import imageLoader from 'imageLoader'; -import globalize from 'globalize'; -import 'emby-itemscontainer'; -import 'emby-button'; +import connectionManager from 'jellyfin-apiclient'; +import listView from '../components/listview/listview'; +import cardBuilder from '../components/cardbuilder/cardBuilder'; +import imageLoader from '../components/images/imageLoader'; +import globalize from './globalize'; +import '../elements/emby-itemscontainer/emby-itemscontainer'; +import '../elements/emby-button/emby-button'; function renderItems(page, item) { const sections = []; diff --git a/src/scripts/keyboardNavigation.js b/src/scripts/keyboardNavigation.js index ec354a7ba3..e10110d5c5 100644 --- a/src/scripts/keyboardNavigation.js +++ b/src/scripts/keyboardNavigation.js @@ -3,8 +3,8 @@ * @module components/input/keyboardnavigation */ -import inputManager from 'inputManager'; -import layoutManager from 'layoutManager'; +import inputManager from './inputManager'; +import layoutManager from '../components/layoutManager'; /** * Key name mapping. @@ -156,7 +156,7 @@ function attachGamepadScript(e) { console.log('Gamepad connected! Attaching gamepadtokey.js script'); window.removeEventListener('gamepadconnected', attachGamepadScript); /* eslint-disable-next-line @babel/no-unused-expressions */ - import('scripts/gamepadtokey'); + import('./gamepadtokey'); } // No need to check for gamepads manually at load time, the eventhandler will be fired for that diff --git a/src/scripts/libraryBrowser.js b/src/scripts/libraryBrowser.js index 5c6db19258..a928902cb4 100644 --- a/src/scripts/libraryBrowser.js +++ b/src/scripts/libraryBrowser.js @@ -1,5 +1,5 @@ -import * as userSettings from 'userSettings'; -import globalize from 'globalize'; +import * as userSettings from './settings/userSettings'; +import globalize from './globalize'; export function getSavedQueryKey(modifier) { return window.location.href.split('#')[0] + (modifier || ''); @@ -55,7 +55,7 @@ export function showLayoutMenu (button, currentLayout, views) { }; }); - import('actionsheet').then(({default: actionsheet}) => { + import('../components/actionSheet/actionSheet').then(({default: actionsheet}) => { actionsheet.show({ items: menuItems, positionTo: button, @@ -120,8 +120,8 @@ export function getQueryPagingHtml (options) { export function showSortMenu (options) { Promise.all([ - import('dialogHelper'), - import('emby-radio') + import('../components/dialogHelper/dialogHelper'), + import('../elements/emby-radio/emby-radio') ]).then(([{default: dialogHelper}]) => { function onSortByChange() { const newValue = this.value; diff --git a/src/scripts/libraryMenu.js b/src/scripts/libraryMenu.js index f2dde3b09e..fcd4e75d55 100644 --- a/src/scripts/libraryMenu.js +++ b/src/scripts/libraryMenu.js @@ -1,20 +1,21 @@ -import dom from 'dom'; -import layoutManager from 'layoutManager'; -import inputManager from 'inputManager'; -import events from 'events'; -import viewManager from 'viewManager'; -import appRouter from 'appRouter'; -import appHost from 'apphost'; -import playbackManager from 'playbackManager'; -import syncPlayManager from 'syncPlayManager'; -import * as groupSelectionMenu from 'groupSelectionMenu'; -import browser from 'browser'; -import globalize from 'globalize'; -import imageHelper from 'scripts/imagehelper'; -import 'paper-icon-button-light'; -import 'material-icons'; -import 'scrollStyles'; -import 'flexStyles'; +import dom from './dom'; +import layoutManager from '../components/layoutManager'; +import inputManager from './inputManager'; +import connectionManager from 'jellyfin-apiclient'; +import events from 'jellyfin-apiclient'; +import viewManager from '../components/viewManager/viewManager'; +import appRouter from '../components/appRouter'; +import appHost from '../components/apphost'; +import playbackManager from '../components/playback/playbackmanager'; +import syncPlayManager from '../components/syncPlay/syncPlayManager'; +import groupSelectionMenu from '../components/syncPlay/groupSelectionMenu'; +import browser from './browser'; +import globalize from './globalize'; +import imageHelper from './imagehelper'; +import '../elements/emby-button/paper-icon-button-light'; +import 'material-design-icons-iconfont'; +import '../assets/css/scrollstyles.css'; +import '../assets/css/flexstyles.css'; /* eslint-disable indent */ @@ -67,7 +68,7 @@ import 'flexStyles'; } function lazyLoadViewMenuBarImages() { - import('imageLoader').then(({default: imageLoader}) => { + import('../components/images/imageLoader').then((imageLoader) => { imageLoader.lazyChildren(skinHeader); }); } @@ -220,7 +221,7 @@ import 'flexStyles'; function onCastButtonClicked() { const btn = this; - import('playerSelectionMenu').then(({default: playerSelectionMenu}) => { + import('../components/playback/playerSelectionMenu').then((playerSelectionMenu) => { playerSelectionMenu.show(btn); }); } @@ -799,7 +800,7 @@ import 'flexStyles'; } function initHeadRoom(elem) { - import('headroom').then(({default: Headroom}) => { + import('headroom.js').then((Headroom) => { const headroom = new Headroom(elem); headroom.init(); }); @@ -839,7 +840,7 @@ import 'flexStyles'; navDrawerScrollContainer = navDrawerElement.querySelector('.scrollContainer'); navDrawerScrollContainer.addEventListener('click', onMainDrawerClick); return new Promise(function (resolve, reject) { - import('navdrawer').then(({default: navdrawer}) => { + import('../libraries/navdrawer/navdrawer').then((navdrawer) => { navDrawerInstance = new navdrawer(getNavDrawerOptions()); if (!layoutManager.tv) { @@ -871,7 +872,7 @@ import 'flexStyles'; let requiresUserRefresh = true; function setTabs (type, selectedIndex, builder) { - import('mainTabsManager').then((mainTabsManager) => { + import('../components/maintabsmanager').then((mainTabsManager) => { if (type) { mainTabsManager.setTabs(viewManager.currentView(), selectedIndex, builder, function () { return []; diff --git a/src/scripts/livetvcomponents.js b/src/scripts/livetvcomponents.js index 46fb714763..9fb999dd03 100644 --- a/src/scripts/livetvcomponents.js +++ b/src/scripts/livetvcomponents.js @@ -1,6 +1,6 @@ -import layoutManager from 'layoutManager'; -import datetime from 'datetime'; -import cardBuilder from 'cardBuilder'; +import layoutManager from '../components/layoutManager'; +import datetime from './datetime'; +import cardBuilder from '../components/cardbuilder/cardBuilder'; function enableScrollX() { return !layoutManager.desktop; diff --git a/src/scripts/mouseManager.js b/src/scripts/mouseManager.js index 40253fb91c..0c942fd4d9 100644 --- a/src/scripts/mouseManager.js +++ b/src/scripts/mouseManager.js @@ -1,9 +1,9 @@ -import inputManager from 'inputManager'; -import focusManager from 'focusManager'; -import browser from 'browser'; -import layoutManager from 'layoutManager'; -import events from 'events'; -import dom from 'dom'; +import inputManager from './inputManager'; +import focusManager from '../components/focusManager'; +import browser from '../scripts/browser'; +import layoutManager from '../components/layoutManager'; +import events from 'jellyfin-apiclient'; +import dom from '../scripts/dom'; /* eslint-disable indent */ const self = {}; diff --git a/src/scripts/multiDownload.js b/src/scripts/multiDownload.js index 6d47427ed8..54921bf4ef 100644 --- a/src/scripts/multiDownload.js +++ b/src/scripts/multiDownload.js @@ -1,4 +1,4 @@ -import browser from 'browser'; +import browser from '../scripts/browser'; function fallback(urls) { let i = 0; diff --git a/src/scripts/playlistedit.js b/src/scripts/playlistedit.js index a4b519e045..1dc5481c1e 100644 --- a/src/scripts/playlistedit.js +++ b/src/scripts/playlistedit.js @@ -1,50 +1,48 @@ -define(['listView'], function (listView) { - 'use strict'; +import listView from '../components/listview/listview'; - function getFetchPlaylistItemsFn(itemId) { - return function () { - const query = { - Fields: 'PrimaryImageAspectRatio,UserData', - EnableImageTypes: 'Primary,Backdrop,Banner,Thumb', - UserId: ApiClient.getCurrentUserId() - }; - return ApiClient.getJSON(ApiClient.getUrl(`Playlists/${itemId}/Items`, query)); +function getFetchPlaylistItemsFn(itemId) { + return function () { + const query = { + Fields: 'PrimaryImageAspectRatio,UserData', + EnableImageTypes: 'Primary,Backdrop,Banner,Thumb', + UserId: ApiClient.getCurrentUserId() }; - } - - function getItemsHtmlFn(itemId) { - return function (items) { - return listView.getListViewHtml({ - items: items, - showIndex: false, - showRemoveFromPlaylist: true, - playFromHere: true, - action: 'playallfromhere', - smallIcon: true, - dragHandle: true, - playlistId: itemId - }); - }; - } - - function init(page, item) { - const elem = page.querySelector('#childrenContent .itemsContainer'); - elem.classList.add('vertical-list'); - elem.classList.remove('vertical-wrap'); - elem.enableDragReordering(true); - elem.fetchData = getFetchPlaylistItemsFn(item.Id); - elem.getItemsHtml = getItemsHtmlFn(item.Id); - } - - window.PlaylistViewer = { - render: function (page, item) { - if (!page.playlistInit) { - page.playlistInit = true; - init(page, item); - } - - page.querySelector('#childrenContent').classList.add('verticalSection-extrabottompadding'); - page.querySelector('#childrenContent .itemsContainer').refreshItems(); - } + return ApiClient.getJSON(ApiClient.getUrl(`Playlists/${itemId}/Items`, query)); }; -}); +} + +function getItemsHtmlFn(itemId) { + return function (items) { + return listView.getListViewHtml({ + items: items, + showIndex: false, + showRemoveFromPlaylist: true, + playFromHere: true, + action: 'playallfromhere', + smallIcon: true, + dragHandle: true, + playlistId: itemId + }); + }; +} + +function init(page, item) { + const elem = page.querySelector('#childrenContent .itemsContainer'); + elem.classList.add('vertical-list'); + elem.classList.remove('vertical-wrap'); + elem.enableDragReordering(true); + elem.fetchData = getFetchPlaylistItemsFn(item.Id); + elem.getItemsHtml = getItemsHtmlFn(item.Id); +} + +window.PlaylistViewer = { + render: function (page, item) { + if (!page.playlistInit) { + page.playlistInit = true; + init(page, item); + } + + page.querySelector('#childrenContent').classList.add('verticalSection-extrabottompadding'); + page.querySelector('#childrenContent .itemsContainer').refreshItems(); + } +}; diff --git a/src/scripts/playlists.js b/src/scripts/playlists.js index bdfd155c55..3f09f621b2 100644 --- a/src/scripts/playlists.js +++ b/src/scripts/playlists.js @@ -1,11 +1,11 @@ -import loading from 'loading'; +import loading from '../../components/loading/loading'; import listView from 'listView'; import cardBuilder from 'cardBuilder'; import libraryMenu from 'libraryMenu'; import libraryBrowser from 'libraryBrowser'; import imageLoader from 'imageLoader'; -import userSettings from 'userSettings'; -import 'emby-itemscontainer'; +import * as userSettings from '../scripts/settings/userSettings'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; export default function (view, params) { function getPageData(context) { diff --git a/src/scripts/routes.js b/src/scripts/routes.js index ebe6f3cf5a..2ebfabbe6c 100644 --- a/src/scripts/routes.js +++ b/src/scripts/routes.js @@ -1,16 +1,16 @@ -import 'emby-button'; -import 'emby-input'; -import 'scripts/livetvcomponents'; -import 'paper-icon-button-light'; -import 'emby-itemscontainer'; -import 'emby-collapse'; -import 'emby-select'; -import 'livetvcss'; -import 'emby-checkbox'; -import 'emby-slider'; -import 'listViewStyle'; -import 'dashboardcss'; -import 'detailtablecss'; +import '../elements/emby-button/emby-button'; +import '../elements/emby-input/emby-input'; +import '../scripts/livetvcomponents'; +import '../elements/emby-button/paper-icon-button-light'; +import '../elements/emby-itemscontainer/emby-itemscontainer'; +import '../elements/emby-collapse/emby-collapse'; +import '../elements/emby-select/emby-select'; +import '../elements/emby-checkbox/emby-checkbox'; +import '../elements/emby-slider/emby-slider'; +import '../assets/css/livetv.css'; +import '../components/listview/listview.css'; +import '../assets/css/dashboard.css'; +import '../assets/css/detailtable.css'; /* eslint-disable indent */ diff --git a/src/scripts/scrollHelper.js b/src/scripts/scrollHelper.js index b867123683..633216dcf8 100644 --- a/src/scripts/scrollHelper.js +++ b/src/scripts/scrollHelper.js @@ -1,6 +1,6 @@ -import focusManager from 'focusManager'; -import dom from 'dom'; -import 'scrollStyles'; +import focusManager from '../components/focusManager'; +import dom from './dom'; +import '../assets/css/scrollstyles.css'; function getBoundingClientRect(elem) { // Support: BlackBerry 5, iOS 3 (original iPhone) diff --git a/src/scripts/serverNotifications.js b/src/scripts/serverNotifications.js index c14a133d6c..7a4a5f3e3d 100644 --- a/src/scripts/serverNotifications.js +++ b/src/scripts/serverNotifications.js @@ -1,9 +1,10 @@ -import playbackManager from 'playbackManager'; -import syncPlayManager from 'syncPlayManager'; -import events from 'events'; -import inputManager from 'inputManager'; -import focusManager from 'focusManager'; -import appRouter from 'appRouter'; +import connectionManager from 'jellyfin-apiclient'; +import playbackManager from '../components/playback/playbackmanager'; +import syncPlayManager from '../components/syncPlay/syncPlayManager'; +import events from 'jellyfin-apiclient'; +import inputManager from '../scripts/inputManager'; +import focusManager from '../components/focusManager'; +import appRouter from '../components/appRouter'; const serverNotifications = {}; @@ -14,11 +15,11 @@ function notifyApp() { function displayMessage(cmd) { const args = cmd.Arguments; if (args.TimeoutMs) { - import('toast').then(({default: toast}) => { + import('../components/toast/toast').then((toast) => { toast({ title: args.Header, text: args.Text }); }); } else { - import('alert').then(({default: alert}) => { + import('../components/alert').then(({default: alert}) => { alert({ title: args.Header, text: args.Text }); }); } diff --git a/src/scripts/settings/appSettings.js b/src/scripts/settings/appSettings.js index ded62c94ae..b167ba93bf 100644 --- a/src/scripts/settings/appSettings.js +++ b/src/scripts/settings/appSettings.js @@ -1,7 +1,5 @@ /* eslint-disable indent */ - -import appStorage from 'appStorage'; -import events from 'events'; +import { appStorage, events } from 'jellyfin-apiclient'; function getKey(name, userId) { if (userId) { diff --git a/src/scripts/settings/userSettings.js b/src/scripts/settings/userSettings.js index 263d74ed37..6ba41ce989 100644 --- a/src/scripts/settings/userSettings.js +++ b/src/scripts/settings/userSettings.js @@ -1,5 +1,5 @@ -import appSettings from 'appSettings'; -import events from 'events'; +import appSettings from './appSettings'; +import events from 'jellyfin-apiclient'; function onSaveTimeout() { const self = this; diff --git a/src/scripts/site.js b/src/scripts/site.js index db22b6a175..77c6279bd6 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -3,10 +3,11 @@ import 'regenerator-runtime/runtime'; import 'jquery'; import 'fast-text-encoding'; import 'intersection-observer'; -import 'classlist-polyfill'; +import 'classlist.js'; import 'whatwg-fetch'; import 'resize-observer-polyfill'; import 'jellyfin-noto'; +import 'webcomponents.js'; import '../assets/css/site.css'; // TODO: Move this elsewhere @@ -91,10 +92,10 @@ function initClient() { function createConnectionManager() { return Promise.all([ - import('jellyfin-apiclient/src/connectionManager'), + import('jellyfin-apiclient'), import('../components/apphost'), - import('jellyfin-apiclient/src/connectionManager'), - import('jellyfin-apiclient/src/events'), + import('jellyfin-apiclient'), + import('jellyfin-apiclient'), import('./settings/userSettings') ]) .then(([ConnectionManager, appHost, credentialProvider, events, userSettings]) => { @@ -114,7 +115,7 @@ function initClient() { console.debug('loading ApiClient singleton'); return Promise.all([ - import('jellyfin-apiclient/src/apiClient'), + import('jellyfin-apiclient'), import('./clientUtils') ]) .then(([apiClientFactory, clientUtils]) => { @@ -165,8 +166,8 @@ function initClient() { }); Promise.all([ import('./globalize'), - import('jellyfin-apiclient/src/connectionManager'), - import('jellyfin-apiclient/src/events') + import('jellyfin-apiclient'), + import('jellyfin-apiclient') ]) .then((globalize, connectionManager, events) => { events.on(connectionManager, 'localusersignedin', globalize.updateCurrentCulture); @@ -246,7 +247,7 @@ function initClient() { console.groupEnd('loading installed plugins'); import('../components/packageManager') .then((packageManager) => { - packageManager.default.init().then(resolve, reject); + packageManager.init().then(resolve, reject); }); }) ; @@ -257,9 +258,9 @@ function initClient() { function loadPlugin(url) { return new Promise(function (resolve, reject) { - import('pluginManager') + import('../components/pluginManager') .then((pluginManager) => { - pluginManager.default.loadPlugin(url).then(resolve, reject); + pluginManager.loadPlugin(url).then(resolve, reject); }); }); } @@ -269,7 +270,7 @@ function initClient() { // ensure that appHost is loaded in this point Promise.all([ - import('jellyfin-apiclient/src/apiClient'), + import('jellyfin-apiclient'), import('../components/appRouter') ]) .then(([appHost, appRouter]) => { diff --git a/src/scripts/taskbutton.js b/src/scripts/taskbutton.js index 43a46301aa..85ee56b862 100644 --- a/src/scripts/taskbutton.js +++ b/src/scripts/taskbutton.js @@ -1,8 +1,8 @@ -import events from 'events'; -import serverNotifications from 'serverNotifications'; -import globalize from 'globalize'; -import 'emby-button'; +import { connectionManager, events } from 'jellyfin-apiclient'; +import serverNotifications from '../scripts/serverNotifications'; +import globalize from '../scripts/globalize'; +import '../elements/emby-button/emby-button'; export default function (options) { function pollTasks() { diff --git a/src/scripts/themeManager.js b/src/scripts/themeManager.js index 56d3362219..f7dcf597d1 100644 --- a/src/scripts/themeManager.js +++ b/src/scripts/themeManager.js @@ -1,4 +1,4 @@ -import * as webSettings from 'webSettings'; +import * as webSettings from './settings/webSettings'; let themeStyleElement = document.querySelector('#cssTheme'); let currentThemeId; diff --git a/src/scripts/touchHelper.js b/src/scripts/touchHelper.js index fa05c83d90..578ca02c0a 100644 --- a/src/scripts/touchHelper.js +++ b/src/scripts/touchHelper.js @@ -1,5 +1,5 @@ -import dom from 'dom'; -import events from 'events'; +import dom from '../scripts/dom'; +import events from 'jellyfin-apiclient'; function getTouches(e) { return e.changedTouches || e.targetTouches || e.touches; From 96eccd2ecdf9914960e2b5f574d2449ffc8642f8 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sat, 15 Aug 2020 12:44:52 +0200 Subject: [PATCH 038/202] Rework Webpack config --- package.json | 312 +----- src/bundle.js | 182 ---- src/{ => scripts}/standalone.js | 0 webpack.common.js | 54 +- webpack.dev.js | 26 +- webpack.prod.js | 1 + yarn.lock | 1695 ++++++++++++++++++------------- 7 files changed, 1034 insertions(+), 1236 deletions(-) delete mode 100644 src/bundle.js rename src/{ => scripts}/standalone.js (100%) diff --git a/package.json b/package.json index 03f27954a7..bfba7b363f 100644 --- a/package.json +++ b/package.json @@ -10,13 +10,13 @@ "@babel/eslint-plugin": "^7.12.1", "@babel/plugin-proposal-class-properties": "^7.10.1", "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/plugin-transform-modules-amd": "^7.12.1", - "@babel/polyfill": "^7.12.1", + "@babel/polyfill": "^7.11.5", "@babel/preset-env": "^7.12.1", "autoprefixer": "^9.8.6", "babel-loader": "^8.0.6", "browser-sync": "^2.26.13", "confusing-browser-globals": "^1.0.10", + "clean-webpack-plugin": "^3.0.0", "copy-webpack-plugin": "^5.1.1", "css-loader": "^5.0.0", "cssnano": "^4.1.10", @@ -40,6 +40,7 @@ "gulp-sass": "^4.0.2", "gulp-sourcemaps": "^2.6.5", "gulp-terser": "^1.4.1", + "html-loader": "^1.1.0", "html-webpack-plugin": "^4.5.0", "lazypipe": "^1.0.2", "node-sass": "^5.0.0", @@ -51,6 +52,8 @@ "stylelint-no-browser-hacks": "^1.2.1", "stylelint-order": "^4.1.0", "webpack": "^5.3.2", + "webpack-cli": "^4.0.0", + "webpack-concat-plugin": "^3.0.0", "webpack-merge": "^4.2.2", "webpack-stream": "^6.1.0", "worker-plugin": "^5.0.0" @@ -87,292 +90,17 @@ }, "babel": { "presets": [ - "@babel/preset-env" + [ + "@babel/preset-env", + { + "useBuiltIns": "usage", + "corejs": 3 + } + ] ], - "overrides": [ - { - "test": [ - "src/components/accessSchedule/accessSchedule.js", - "src/components/actionSheet/actionSheet.js", - "src/components/activitylog.js", - "src/components/alert.js", - "src/components/alphaPicker/alphaPicker.js", - "src/components/appFooter/appFooter.js", - "src/components/apphost.js", - "src/components/appRouter.js", - "src/components/autoFocuser.js", - "src/components/backdrop/backdrop.js", - "src/components/cardbuilder/cardBuilder.js", - "src/components/cardbuilder/chaptercardbuilder.js", - "src/components/cardbuilder/peoplecardbuilder.js", - "src/components/channelMapper/channelMapper.js", - "src/components/collectionEditor/collectionEditor.js", - "src/components/confirm/confirm.js", - "src/components/dialog/dialog.js", - "src/components/dialogHelper/dialogHelper.js", - "src/components/directorybrowser/directorybrowser.js", - "src/components/displaySettings/displaySettings.js", - "src/components/favoriteitems.js", - "src/components/fetchhelper.js", - "src/components/filterdialog/filterdialog.js", - "src/components/filtermenu/filtermenu.js", - "src/components/focusManager.js", - "src/components/groupedcards.js", - "src/components/guide/guide.js", - "src/components/guide/guide-settings.js", - "src/components/homeScreenSettings/homeScreenSettings.js", - "src/components/homesections/homesections.js", - "src/components/htmlMediaHelper.js", - "src/components/imageOptionsEditor/imageOptionsEditor.js", - "src/components/images/imageLoader.js", - "src/components/imageDownloader/imageDownloader.js", - "src/components/imageeditor/imageeditor.js", - "src/components/imageUploader/imageUploader.js", - "src/components/indicators/indicators.js", - "src/components/itemContextMenu.js", - "src/components/itemHelper.js", - "src/components/itemidentifier/itemidentifier.js", - "src/components/itemMediaInfo/itemMediaInfo.js", - "src/components/itemsrefresher.js", - "src/components/layoutManager.js", - "src/components/lazyLoader/lazyLoaderIntersectionObserver.js", - "src/components/libraryoptionseditor/libraryoptionseditor.js", - "src/components/listview/listview.js", - "src/components/loading/loading.js", - "src/components/maintabsmanager.js", - "src/components/mediainfo/mediainfo.js", - "src/components/mediaLibraryCreator/mediaLibraryCreator.js", - "src/components/mediaLibraryEditor/mediaLibraryEditor.js", - "src/components/metadataEditor/metadataEditor.js", - "src/components/metadataEditor/personEditor.js", - "src/components/multiSelect/multiSelect.js", - "src/components/notifications/notifications.js", - "src/components/nowPlayingBar/nowPlayingBar.js", - "src/components/packageManager.js", - "src/components/playback/brightnessosd.js", - "src/components/playback/mediasession.js", - "src/components/playback/nowplayinghelper.js", - "src/components/playback/playbackorientation.js", - "src/components/playback/playbackmanager.js", - "src/components/playback/playerSelectionMenu.js", - "src/components/playback/playersettingsmenu.js", - "src/components/playback/playmethodhelper.js", - "src/components/playback/playqueuemanager.js", - "src/components/playback/remotecontrolautoplay.js", - "src/components/playback/volumeosd.js", - "src/components/playbackSettings/playbackSettings.js", - "src/components/playerstats/playerstats.js", - "src/components/playlisteditor/playlisteditor.js", - "src/components/playmenu.js", - "src/components/pluginManager.js", - "src/components/prompt/prompt.js", - "src/components/qualityOptions.js", - "src/components/quickConnectSettings/quickConnectSettings.js", - "src/components/recordingcreator/recordingbutton.js", - "src/components/recordingcreator/recordingcreator.js", - "src/components/recordingcreator/seriesrecordingeditor.js", - "src/components/recordingcreator/recordinghelper.js", - "src/components/refreshdialog/refreshdialog.js", - "src/components/recordingcreator/recordingeditor.js", - "src/components/recordingcreator/recordingfields.js", - "src/components/remotecontrol/remotecontrol.js", - "src/components/sanatizefilename.js", - "src/components/scrollManager.js", - "src/plugins/experimentalWarnings/plugin.js", - "src/plugins/sessionPlayer/plugin.js", - "src/plugins/htmlAudioPlayer/plugin.js", - "src/plugins/comicsPlayer/plugin.js", - "src/plugins/chromecastPlayer/plugin.js", - "src/components/slideshow/slideshow.js", - "src/components/sortmenu/sortmenu.js", - "src/plugins/htmlVideoPlayer/plugin.js", - "src/plugins/logoScreensaver/plugin.js", - "src/plugins/playAccessValidation/plugin.js", - "src/components/search/searchfields.js", - "src/components/search/searchresults.js", - "src/components/settingshelper.js", - "src/components/shortcuts.js", - "src/components/subtitleeditor/subtitleeditor.js", - "src/components/subtitlesync/subtitlesync.js", - "src/components/subtitlesettings/subtitleappearancehelper.js", - "src/components/subtitlesettings/subtitlesettings.js", - "src/components/syncPlay/groupSelectionMenu.js", - "src/components/syncPlay/playbackPermissionManager.js", - "src/components/syncPlay/syncPlayManager.js", - "src/components/syncPlay/timeSyncManager.js", - "src/components/themeMediaPlayer.js", - "src/components/tabbedview/tabbedview.js", - "src/components/viewManager/viewManager.js", - "src/components/tvproviders/schedulesdirect.js", - "src/components/tvproviders/xmltv.js", - "src/components/toast/toast.js", - "src/components/tunerPicker.js", - "src/components/upnextdialog/upnextdialog.js", - "src/components/userdatabuttons/userdatabuttons.js", - "src/components/viewContainer.js", - "src/components/viewSettings/viewSettings.js", - "src/components/castSenderApi.js", - "src/controllers/session/addServer/index.js", - "src/controllers/session/forgotPassword/index.js", - "src/controllers/session/resetPassword/index.js", - "src/controllers/session/login/index.js", - "src/controllers/session/selectServer/index.js", - "src/controllers/dashboard/apikeys.js", - "src/controllers/dashboard/dashboard.js", - "src/controllers/dashboard/devices/device.js", - "src/controllers/dashboard/devices/devices.js", - "src/controllers/dashboard/dlna/profile.js", - "src/controllers/dashboard/dlna/profiles.js", - "src/controllers/dashboard/dlna/settings.js", - "src/controllers/dashboard/encodingsettings.js", - "src/controllers/dashboard/general.js", - "src/controllers/dashboard/librarydisplay.js", - "src/controllers/dashboard/logs.js", - "src/controllers/music/musicalbums.js", - "src/controllers/music/musicartists.js", - "src/controllers/music/musicgenres.js", - "src/controllers/music/musicplaylists.js", - "src/controllers/music/musicrecommended.js", - "src/controllers/music/songs.js", - "src/controllers/dashboard/library.js", - "src/controllers/dashboard/metadataImages.js", - "src/controllers/dashboard/metadatanfo.js", - "src/controllers/dashboard/networking.js", - "src/controllers/dashboard/notifications/notification/index.js", - "src/controllers/dashboard/notifications/notifications/index.js", - "src/controllers/dashboard/playback.js", - "src/controllers/dashboard/plugins/add/index.js", - "src/controllers/dashboard/plugins/installed/index.js", - "src/controllers/dashboard/plugins/available/index.js", - "src/controllers/dashboard/plugins/repositories/index.js", - "src/controllers/dashboard/quickConnect.js", - "src/controllers/dashboard/scheduledtasks/scheduledtask.js", - "src/controllers/dashboard/scheduledtasks/scheduledtasks.js", - "src/controllers/dashboard/serveractivity.js", - "src/controllers/dashboard/streaming.js", - "src/controllers/dashboard/users/useredit.js", - "src/controllers/dashboard/users/userlibraryaccess.js", - "src/controllers/dashboard/users/usernew.js", - "src/controllers/dashboard/users/userparentalcontrol.js", - "src/controllers/dashboard/users/userpasswordpage.js", - "src/controllers/dashboard/users/userprofilespage.js", - "src/controllers/home.js", - "src/controllers/list.js", - "src/controllers/edititemmetadata.js", - "src/controllers/favorites.js", - "src/controllers/hometab.js", - "src/controllers/movies/moviecollections.js", - "src/controllers/movies/moviegenres.js", - "src/controllers/movies/movies.js", - "src/controllers/movies/moviesrecommended.js", - "src/controllers/movies/movietrailers.js", - "src/controllers/playback/nowplaying.js", - "src/controllers/playback/videoosd.js", - "src/controllers/itemDetails/index.js", - "src/controllers/playback/queue/index.js", - "src/controllers/playback/video/index.js", - "src/controllers/searchpage.js", - "src/controllers/livetv/livetvguide.js", - "src/controllers/livetvtuner.js", - "src/controllers/livetv/livetvsuggested.js", - "src/controllers/livetvstatus.js", - "src/controllers/livetvguideprovider.js", - "src/controllers/livetvsettings.js", - "src/controllers/livetv/livetvrecordings.js", - "src/controllers/livetv/livetvschedule.js", - "src/controllers/livetv/livetvseriestimers.js", - "src/controllers/livetv/livetvchannels.js", - "src/controllers/shows/episodes.js", - "src/controllers/shows/tvgenres.js", - "src/controllers/shows/tvlatest.js", - "src/controllers/shows/tvrecommended.js", - "src/controllers/shows/tvshows.js", - "src/controllers/shows/tvstudios.js", - "src/controllers/shows/tvupcoming.js", - "src/controllers/user/display/index.js", - "src/controllers/user/home/index.js", - "src/controllers/user/menu/index.js", - "src/controllers/user/playback/index.js", - "src/controllers/user/profile/index.js", - "src/controllers/user/quickConnect/index.js", - "src/controllers/user/subtitles/index.js", - "src/controllers/wizard/finish/index.js", - "src/controllers/wizard/remote/index.js", - "src/controllers/wizard/settings/index.js", - "src/controllers/wizard/start/index.js", - "src/controllers/wizard/user/index.js", - "src/elements/emby-button/emby-button.js", - "src/elements/emby-button/paper-icon-button-light.js", - "src/elements/emby-checkbox/emby-checkbox.js", - "src/elements/emby-collapse/emby-collapse.js", - "src/elements/emby-input/emby-input.js", - "src/elements/emby-itemrefreshindicator/emby-itemrefreshindicator.js", - "src/elements/emby-itemscontainer/emby-itemscontainer.js", - "src/elements/emby-playstatebutton/emby-playstatebutton.js", - "src/elements/emby-programcell/emby-programcell.js", - "src/elements/emby-progressbar/emby-progressbar.js", - "src/elements/emby-progressring/emby-progressring.js", - "src/elements/emby-radio/emby-radio.js", - "src/elements/emby-ratingbutton/emby-ratingbutton.js", - "src/elements/emby-scrollbuttons/emby-scrollbuttons.js", - "src/elements/emby-scroller/emby-scroller.js", - "src/elements/emby-select/emby-select.js", - "src/elements/emby-slider/emby-slider.js", - "src/elements/emby-tabs/emby-tabs.js", - "src/elements/emby-textarea/emby-textarea.js", - "src/elements/emby-toggle/emby-toggle.js", - "src/libraries/screensavermanager.js", - "src/libraries/navdrawer/navdrawer.js", - "src/libraries/scroller.js", - "src/plugins/backdropScreensaver/plugin.js", - "src/plugins/bookPlayer/plugin.js", - "src/plugins/pdfPlayer/plugin.js", - "src/plugins/bookPlayer/tableOfContents.js", - "src/plugins/chromecastPlayer/chromecastHelper.js", - "src/plugins/photoPlayer/plugin.js", - "src/plugins/youtubePlayer/plugin.js", - "src/scripts/alphanumericshortcuts.js", - "src/scripts/autoBackdrops.js", - "src/scripts/autocast.js", - "src/scripts/browser.js", - "src/scripts/clientUtils.js", - "src/scripts/datetime.js", - "src/scripts/deleteHelper.js", - "src/scripts/dfnshelper.js", - "src/scripts/dom.js", - "src/scripts/editorsidebar.js", - "src/scripts/fileDownloader.js", - "src/scripts/filesystem.js", - "src/scripts/globalize.js", - "src/scripts/imagehelper.js", - "src/scripts/itembynamedetailpage.js", - "src/scripts/inputManager.js", - "src/scripts/autoThemes.js", - "src/scripts/themeManager.js", - "src/scripts/keyboardNavigation.js", - "src/scripts/libraryMenu.js", - "src/scripts/libraryBrowser.js", - "src/scripts/livetvcomponents.js", - "src/scripts/mouseManager.js", - "src/scripts/multiDownload.js", - "src/scripts/playlists.js", - "src/scripts/scrollHelper.js", - "src/scripts/serverNotifications.js", - "src/scripts/routes.js", - "src/scripts/settings/appSettings.js", - "src/scripts/settings/userSettings.js", - "src/scripts/settings/webSettings.js", - "src/scripts/shell.js", - "src/scripts/taskbutton.js", - "src/scripts/themeLoader.js", - "src/scripts/touchHelper.js" - ], - "plugins": [ - "@babel/plugin-transform-modules-amd", - "@babel/plugin-proposal-class-properties", - "@babel/plugin-proposal-private-methods" - ] - } + "plugins": [ + "@babel/plugin-proposal-class-properties", + "@babel/plugin-proposal-private-methods" ] }, "browserslist": [ @@ -393,11 +121,11 @@ ], "scripts": { "start": "yarn serve", - "serve": "gulp serve --development", - "prepare": "gulp --production", - "build:development": "gulp --development", - "build:production": "gulp --production", - "build:standalone": "gulp standalone --development", + "serve": "webpack-dev-server --config webpack.dev.js --open", + "prepare": "webpack --config webpack.prod.js", + "build:development": "webpack --config webpack.dev.js", + "build:production": "webpack --config webpack.prod.js", + "build:standalone": "webpack --config webpack.standalone.js", "lint": "eslint \".\"", "stylelint": "stylelint \"src/**/*.css\"" } diff --git a/src/bundle.js b/src/bundle.js deleted file mode 100644 index 9363cd8852..0000000000 --- a/src/bundle.js +++ /dev/null @@ -1,182 +0,0 @@ -/** - * require.js module definitions bundled by webpack - */ -// Use define from require.js not webpack's define -const _define = window.define; - -// fetch -const fetch = require('whatwg-fetch'); -_define('fetch', function() { - return fetch; -}); - -// Blurhash -const blurhash = require('blurhash'); -_define('blurhash', function() { - return blurhash; -}); - -// query-string -const query = require('query-string'); -_define('queryString', function() { - return query; -}); - -// flvjs -const flvjs = require('flv.js/dist/flv').default; -_define('flvjs', function() { - return flvjs; -}); - -// jstree -const jstree = require('jstree'); -require('jstree/dist/themes/default/style.css'); -_define('jstree', function() { - return jstree; -}); - -// jquery -const jquery = require('jquery'); -_define('jQuery', function() { - return jquery; -}); - -// hlsjs -const hlsjs = require('hls.js'); -_define('hlsjs', function() { - return hlsjs; -}); - -// howler -const howler = require('howler'); -_define('howler', function() { - return howler; -}); - -// resize-observer-polyfill -const resize = require('resize-observer-polyfill').default; -_define('resize-observer-polyfill', function() { - return resize; -}); - -// swiper -const swiper = require('swiper/swiper-bundle'); -require('swiper/swiper-bundle.css'); -_define('swiper', function() { - return swiper; -}); - -// sortable -const sortable = require('sortablejs').default; -_define('sortable', function() { - return sortable; -}); - -// webcomponents -const webcomponents = require('webcomponents.js/webcomponents-lite'); -_define('webcomponents', function() { - return webcomponents; -}); - -// libass-wasm -const libassWasm = require('libass-wasm'); -_define('JavascriptSubtitlesOctopus', function() { - return libassWasm; -}); - -// material-icons -const materialIcons = require('material-design-icons-iconfont/dist/material-design-icons.css'); -_define('material-design-icons-iconfont', function() { - return materialIcons; -}); - -const epubjs = require('epubjs'); -_define('epubjs', function () { - return epubjs; -}); - -const pdfjs = require('pdfjs-dist/build/pdf'); -_define('pdfjs', function () { - return pdfjs; -}); - -// page.js -const page = require('page'); -_define('page', function() { - return page; -}); - -// core-js -const polyfill = require('@babel/polyfill/dist/polyfill'); -_define('polyfill', function () { - return polyfill; -}); - -// domtokenlist-shim -const classlist = require('classlist.js'); -_define('classlist-polyfill', function () { - return classlist; -}); - -// Date-FNS -const dateFns = require('date-fns'); -_define('date-fns', function () { - return dateFns; -}); - -const dateFnsLocale = require('date-fns/locale'); -_define('date-fns/locale', function () { - return dateFnsLocale; -}); - -const fast_text_encoding = require('fast-text-encoding'); -_define('fast-text-encoding', function () { - return fast_text_encoding; -}); - -// intersection-observer -const intersection_observer = require('intersection-observer'); -_define('intersection-observer', function () { - return intersection_observer; -}); - -// screenfull -const screenfull = require('screenfull'); -_define('screenfull', function () { - return screenfull; -}); - -// headroom.js -const headroom = require('headroom.js/dist/headroom'); -_define('headroom', function () { - return headroom; -}); - -// apiclient -const apiclient = require('jellyfin-apiclient'); - -_define('apiclient', function () { - return apiclient.ApiClient; -}); - -_define('events', function () { - return apiclient.Events; -}); - -_define('credentialprovider', function () { - return apiclient.Credentials; -}); - -_define('connectionManagerFactory', function () { - return apiclient.ConnectionManager; -}); - -_define('appStorage', function () { - return apiclient.AppStorage; -}); - -// libarchive.js -const libarchive = require('libarchive.js'); -_define('libarchive', function () { - return libarchive; -}); diff --git a/src/standalone.js b/src/scripts/standalone.js similarity index 100% rename from src/standalone.js rename to src/scripts/standalone.js diff --git a/webpack.common.js b/webpack.common.js index f93f816ed6..59f78e7554 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -1,57 +1,19 @@ const path = require('path'); - -const CopyPlugin = require('copy-webpack-plugin'); -const WorkerPlugin = require('worker-plugin'); - -const Assets = [ - 'alameda/alameda.js', - 'native-promise-only/npo.js', - 'libarchive.js/dist/worker-bundle.js', - 'libass-wasm/dist/js/subtitles-octopus-worker.js', - 'libass-wasm/dist/js/subtitles-octopus-worker.data', - 'libass-wasm/dist/js/subtitles-octopus-worker.wasm', - 'libass-wasm/dist/js/subtitles-octopus-worker-legacy.js', - 'libass-wasm/dist/js/subtitles-octopus-worker-legacy.data', - 'libass-wasm/dist/js/subtitles-octopus-worker-legacy.js.mem', - 'pdfjs-dist/build/pdf.worker.js' -]; - -const LibarchiveWasm = [ - 'libarchive.js/dist/wasm-gen/libarchive.js', - 'libarchive.js/dist/wasm-gen/libarchive.wasm' -]; +const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { context: path.resolve(__dirname, 'src'), - entry: './bundle.js', - stats: 'errors-only', + target: 'web', resolve: { modules: [ path.resolve(__dirname, 'node_modules') ] }, - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist'), - libraryTarget: 'amd-require' - }, plugins: [ - new CopyPlugin( - Assets.map(asset => { - return { - from: path.resolve(__dirname, `./node_modules/${asset}`), - to: path.resolve(__dirname, './dist/libraries') - }; - }) - ), - new CopyPlugin( - LibarchiveWasm.map(asset => { - return { - from: path.resolve(__dirname, `./node_modules/${asset}`), - to: path.resolve(__dirname, './dist/libraries/wasm-gen/') - }; - }) - ), - new WorkerPlugin() - ] + (new CleanWebpackPlugin()) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } }; diff --git a/webpack.dev.js b/webpack.dev.js index 33e171daa8..9c52bef3b4 100644 --- a/webpack.dev.js +++ b/webpack.dev.js @@ -1,18 +1,20 @@ -const path = require('path'); const common = require('./webpack.common'); const merge = require('webpack-merge'); const packageConfig = require('./package.json'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = merge(common, { mode: 'development', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist'), - libraryTarget: 'amd-require' - }, - devtool: 'inline-source-map', + entry: './scripts/standalone.js', + devtool: 'source-map', module: { rules: [ + { + test: /\.(html)$/, + use: { + loader: 'html-loader' + } + }, { test: /\.js$/, exclude: /node_modules[\\/](?!date-fns|epubjs|libarchive|jellyfin-apiclient|query-string|split-on-first|strict-uri-encode|xmldom)/, @@ -39,7 +41,7 @@ module.exports = merge(common, { ] }, { - test: /\.(png|jpg|gif)$/i, + test: /\.(png|jpg|gif|svg)$/i, use: ['file-loader'] }, { @@ -53,5 +55,11 @@ module.exports = merge(common, { use: ['file-loader'] } ] - } + }, + plugins: [ + new HtmlWebpackPlugin({ + filename: 'index.html', + template: 'index.html' + }) + ] }); diff --git a/webpack.prod.js b/webpack.prod.js index 408eb4bb59..d27e32b7ad 100644 --- a/webpack.prod.js +++ b/webpack.prod.js @@ -4,6 +4,7 @@ const packageConfig = require('./package.json'); module.exports = merge(common, { mode: 'production', + entry: './scripts/site.js', module: { rules: [ { diff --git a/yarn.lock b/yarn.lock index 31abce5fd0..6c0535a82d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,10 +9,10 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/compat-data@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.1.tgz#d7386a689aa0ddf06255005b4b991988021101a0" - integrity sha512-725AQupWJZ8ba0jbKceeFblZTY90McUBWMwHhkFQ9q1zKPJ95GUktljFcgcsIVwRnTnRKlcYzfiNImg5G9m6ZQ== +"@babel/compat-data@^7.12.1", "@babel/compat-data@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.5.tgz#f56db0c4bb1bbbf221b4e81345aab4141e7cb0e9" + integrity sha512-DTsS7cxrsH3by8nqQSpFSyjSfSYl57D6Cf4q8dW3LK83tBKBDCkfcay1nYkXq1nIHXnpX8WMMb/O25HOy3h1zg== "@babel/core@>=7.2.2", "@babel/core@>=7.9.0", "@babel/core@^7.12.3": version "7.12.3" @@ -52,12 +52,12 @@ dependencies: eslint-rule-composer "^0.3.0" -"@babel/generator@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.1.tgz#0d70be32bdaa03d7c51c8597dda76e0df1f15468" - integrity sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg== +"@babel/generator@^7.12.1", "@babel/generator@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.5.tgz#a2c50de5c8b6d708ab95be5e6053936c1884a4de" + integrity sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A== dependencies: - "@babel/types" "^7.12.1" + "@babel/types" "^7.12.5" jsesc "^2.5.1" source-map "^0.5.0" @@ -77,13 +77,13 @@ "@babel/types" "^7.10.4" "@babel/helper-compilation-targets@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.1.tgz#310e352888fbdbdd8577be8dfdd2afb9e7adcf50" - integrity sha512-jtBEif7jsPwP27GPHs06v4WBV0KrE8a/P7n0N0sSvHn2hwUCYnolP/CLmz51IzAW4NlN+HuoBtb9QcwnRo9F/g== + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" + integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== dependencies: - "@babel/compat-data" "^7.12.1" + "@babel/compat-data" "^7.12.5" "@babel/helper-validator-option" "^7.12.1" - browserslist "^4.12.0" + browserslist "^4.14.5" semver "^5.5.0" "@babel/helper-create-class-features-plugin@^7.12.1": @@ -107,21 +107,20 @@ regexpu-core "^4.7.1" "@babel/helper-define-map@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.4.tgz#f037ad794264f729eda1889f4ee210b870999092" - integrity sha512-nIij0oKErfCnLUCWaCaHW0Bmtl2RO9cN7+u2QT8yqTywgALKlyUVOvHDElh+b5DwVC6YB1FOYFOTWcN/+41EDA== + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" + integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== dependencies: "@babel/helper-function-name" "^7.10.4" - "@babel/types" "^7.10.4" - lodash "^4.17.13" + "@babel/types" "^7.10.5" + lodash "^4.17.19" "@babel/helper-explode-assignable-expression@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz#40a1cd917bff1288f699a94a75b37a1a2dbd8c7c" - integrity sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A== + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz#8006a466695c4ad86a2a5f2fb15b5f2c31ad5633" + integrity sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA== dependencies: - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.1" "@babel/helper-function-name@^7.10.4": version "7.10.4" @@ -154,11 +153,11 @@ "@babel/types" "^7.12.1" "@babel/helper-module-imports@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.1.tgz#1644c01591a15a2f084dd6d092d9430eb1d1216c" - integrity sha512-ZeC1TlMSvikvJNy1v/wPIazCu3NdOwgYZLIkmIyAsGhqkNpiDoQQRmaCK8YP4Pq3GPTLPV9WXaPCJKvx06JxKA== + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" + integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA== dependencies: - "@babel/types" "^7.12.1" + "@babel/types" "^7.12.5" "@babel/helper-module-transforms@^7.12.1": version "7.12.1" @@ -188,11 +187,11 @@ integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== "@babel/helper-regex@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.4.tgz#59b373daaf3458e5747dece71bbaf45f9676af6d" - integrity sha512-inWpnHGgtg5NOF0eyHlC0/74/VkdRITY9dtTpB2PrxKKn+AkVMRiZz/Adrx+Ssg+MLDesi2zohBW6MVq6b4pOQ== + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" + integrity sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg== dependencies: - lodash "^4.17.13" + lodash "^4.17.19" "@babel/helper-remap-async-to-generator@^7.12.1": version "7.12.1" @@ -204,14 +203,14 @@ "@babel/types" "^7.12.1" "@babel/helper-replace-supers@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.1.tgz#f15c9cc897439281891e11d5ce12562ac0cf3fa9" - integrity sha512-zJjTvtNJnCFsCXVi5rUInstLd/EIVNmIKA1Q9ynESmMBWPWd+7sdR+G4/wdu+Mppfep0XLyG2m7EBPvjCeFyrw== + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz#f009a17543bbbbce16b06206ae73b63d3fca68d9" + integrity sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA== dependencies: "@babel/helper-member-expression-to-functions" "^7.12.1" "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/traverse" "^7.12.1" - "@babel/types" "^7.12.1" + "@babel/traverse" "^7.12.5" + "@babel/types" "^7.12.5" "@babel/helper-simple-access@^7.12.1": version "7.12.1" @@ -227,14 +226,7 @@ dependencies: "@babel/types" "^7.12.1" -"@babel/helper-split-export-declaration@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz#2c70576eaa3b5609b24cb99db2888cc3fc4251d1" - integrity sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg== - dependencies: - "@babel/types" "^7.10.4" - -"@babel/helper-split-export-declaration@^7.11.0": +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== @@ -252,9 +244,9 @@ integrity sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A== "@babel/helper-wrap-function@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" - integrity sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug== + version "7.12.3" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz#3332339fc4d1fbbf1c27d7958c27d34708e990d9" + integrity sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow== dependencies: "@babel/helper-function-name" "^7.10.4" "@babel/template" "^7.10.4" @@ -262,13 +254,13 @@ "@babel/types" "^7.10.4" "@babel/helpers@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.1.tgz#8a8261c1d438ec18cb890434df4ec768734c1e79" - integrity sha512-9JoDSBGoWtmbay98efmT2+mySkwjzeFeAL9BuWNoVQpkPFQF8SIIFUfY5os9u8wVzglzoiPRSW7cuJmBDUt43g== + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" + integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== dependencies: "@babel/template" "^7.10.4" - "@babel/traverse" "^7.12.1" - "@babel/types" "^7.12.1" + "@babel/traverse" "^7.12.5" + "@babel/types" "^7.12.5" "@babel/highlight@^7.10.4": version "7.10.4" @@ -279,10 +271,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.10.4", "@babel/parser@^7.12.1", "@babel/parser@^7.12.3": - version "7.12.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.3.tgz#a305415ebe7a6c7023b40b5122a0662d928334cd" - integrity sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw== +"@babel/parser@^7.10.4", "@babel/parser@^7.12.3", "@babel/parser@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.5.tgz#b4af32ddd473c0bfa643bd7ff0728b8e71b81ea0" + integrity sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ== "@babel/plugin-proposal-async-generator-functions@^7.12.1": version "7.12.1" @@ -342,9 +334,9 @@ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" "@babel/plugin-proposal-numeric-separator@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.1.tgz#0e2c6774c4ce48be412119b4d693ac777f7685a6" - integrity sha512-MR7Ok+Af3OhNTCxYVjJZHS0t97ydnJZt/DbR4WISO39iDnhiD8XHrY12xuSJ90FFEGjir0Fzyyn7g/zY6hxbxA== + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.5.tgz#b1ce757156d40ed79d59d467cb2b154a5c4149ba" + integrity sha512-UiAnkKuOrCyjZ3sYNHlRlfuZJbBHknMQ9VMwVeX97Ofwx7RpD6gS2HfqTCh8KNUQgcOm8IKt103oR4KIjh7Q8g== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-numeric-separator" "^7.10.4" @@ -725,7 +717,7 @@ "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/polyfill@^7.12.1": +"@babel/polyfill@^7.11.5": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.12.1.tgz#1f2d6371d1261bbd961f3c5d5909150e12d0bd96" integrity sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g== @@ -806,9 +798,9 @@ semver "^5.5.0" "@babel/preset-modules@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" - integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== + version "0.1.4" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" + integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" @@ -817,9 +809,9 @@ esutils "^2.0.2" "@babel/runtime@^7.8.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.4.tgz#a6724f1a6b8d2f6ea5236dbfe58c7d7ea9c5eb99" - integrity sha512-UpTN5yUJr9b4EX2CnGNWIvER7Ab83ibv0pcvvHc4UOdrBI5jb8bj+32cCwPX6xu0mt2daFNjYhoi+X7beH0RSw== + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" + integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== dependencies: regenerator-runtime "^0.13.4" @@ -832,25 +824,25 @@ "@babel/parser" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.1.tgz#941395e0c5cc86d5d3e75caa095d3924526f0c1e" - integrity sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw== +"@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.5.tgz#78a0c68c8e8a35e4cacfd31db8bb303d5606f095" + integrity sha512-xa15FbQnias7z9a62LwYAA5SZZPkHIXpd42C6uW68o8uTuua96FHZy1y61Va5P/i83FAAcMpW8+A/QayntzuqA== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.1" + "@babel/generator" "^7.12.5" "@babel/helper-function-name" "^7.10.4" "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/parser" "^7.12.1" - "@babel/types" "^7.12.1" + "@babel/parser" "^7.12.5" + "@babel/types" "^7.12.5" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.1.tgz#e109d9ab99a8de735be287ee3d6a9947a190c4ae" - integrity sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA== +"@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.5", "@babel/types@^7.4.4": + version "7.12.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.6.tgz#ae0e55ef1cce1fbc881cd26f8234eb3e657edc96" + integrity sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA== dependencies: "@babel/helper-validator-identifier" "^7.10.4" lodash "^4.17.19" @@ -955,11 +947,6 @@ resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA== -"@types/color-name@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" - integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== - "@types/eslint-scope@^3.7.0": version "3.7.0" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.0.tgz#4792816e31119ebd506902a482caec4951fabd86" @@ -981,35 +968,24 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884" integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g== -"@types/events@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" - integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== - "@types/glob@^7.1.1": - version "7.1.1" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" - integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== + version "7.1.3" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" + integrity sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w== dependencies: - "@types/events" "*" "@types/minimatch" "*" "@types/node" "*" "@types/html-minifier-terser@^5.0.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.0.tgz#551a4589b6ee2cc9c1dff08056128aec29b94880" - integrity sha512-iYCgjm1dGPRuo12+BStjd1HiVQqhlRhWDOQigNxn023HcjnhsiFz9pc6CzJj4HwDCSQca9bxTL4PxJDbkdm3PA== + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#3c9ee980f1a10d6021ae6632ca3e79ca2ec4fb50" + integrity sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA== -"@types/json-schema@*", "@types/json-schema@^7.0.6": +"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": version "7.0.6" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== -"@types/json-schema@^7.0.5": - version "7.0.5" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" - integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== - "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" @@ -1033,9 +1009,9 @@ integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= "@types/node@*": - version "13.13.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.4.tgz#1581d6c16e3d4803eb079c87d4ac893ee7501c2c" - integrity sha512-x26ur3dSXgv5AwKS0lNfbjpCakGIduWU1DU91Zz58ONRWrIKGunmZBNv4P7N+e27sJkiGDsw/3fT4AtsqQBrBA== + version "14.14.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.6.tgz#146d3da57b3c636cc0d1769396ce1cfa8991147f" + integrity sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -1048,9 +1024,9 @@ integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== "@types/q@^1.5.1": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" - integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== + version "1.5.4" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" + integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== "@types/source-list-map@*": version "0.1.2" @@ -1058,14 +1034,14 @@ integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== "@types/tapable@*", "@types/tapable@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.5.tgz#9adbc12950582aa65ead76bffdf39fe0c27a3c02" - integrity sha512-/gG2M/Imw7cQFp8PGvz/SwocNrmKFjFsm5Pb8HdbHkZ1K8pmuPzOX4VeVoiEecFCVf4CsN1r3/BRvx+6sNqwtQ== + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74" + integrity sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA== "@types/uglify-js@*": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.9.0.tgz#4490a140ca82aa855ad68093829e7fd6ae94ea87" - integrity sha512-3ZcoyPYHVOCcLpnfZwD47KFLr8W/mpUcgjpf1M4Q78TMJIw7KMAHSjiCLJp1z3ZrBR9pTLbe191O0TldFK5zcw== + version "3.11.1" + resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.11.1.tgz#97ff30e61a0aa6876c270b5f538737e2d6ab8ceb" + integrity sha512-7npvPKV+jINLu1SpSYVWG8KvyJBhBa8tmzMMdDoVc2pWUYHN8KIXlPJhjJ4LT97c4dXJA2SHL/q6ADbDriZN+Q== dependencies: source-map "^0.6.1" @@ -1091,18 +1067,18 @@ "@types/vfile-message" "*" "@types/webpack-sources@*": - version "0.1.7" - resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-0.1.7.tgz#0a330a9456113410c74a5d64180af0cbca007141" - integrity sha512-XyaHrJILjK1VHVC4aVlKsdNN5KBTwufMb43cQs+flGxtPAf/1Qwl8+Q0tp5BwEGaI8D6XT1L+9bSWXckgkjTLw== + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-2.0.0.tgz#08216ab9be2be2e1499beaebc4d469cec81e82a7" + integrity sha512-a5kPx98CNFRKQ+wqawroFunvFqv7GHm/3KOI52NY9xWADgc8smu4R6prt4EU/M4QfVjvgBkMqU4fBhw3QfMVkg== dependencies: "@types/node" "*" "@types/source-list-map" "*" - source-map "^0.6.1" + source-map "^0.7.3" -"@types/webpack@^4.41.8": - version "4.41.12" - resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.12.tgz#0386ee2a2814368e2f2397abb036c0bf173ff6c3" - integrity sha512-BpCtM4NnBen6W+KEhrL9jKuZCXVtiH6+0b6cxdvNt2EwU949Al334PjQSl2BeAyvAX9mgoNNG21wvjP3xZJJ5w== +"@types/webpack@^4.4.31", "@types/webpack@^4.41.8": + version "4.41.24" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.24.tgz#75b664abe3d5bcfe54e64313ca3b43e498550422" + integrity sha512-1A0MXPwZiMOD3DPMuOKUKcpkdPo8Lq33UGggZ7xio6wJ/jV1dAu5cXDrOfGDnldUroPIRLsr/DT43/GqOA4RFQ== dependencies: "@types/anymatch" "*" "@types/node" "*" @@ -1256,6 +1232,18 @@ "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" +"@webpack-cli/info@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.1.0.tgz#c596d5bc48418b39df00c5ed7341bf0f102dbff1" + integrity sha512-uNWSdaYHc+f3LdIZNwhdhkjjLDDl3jP2+XBqAq9H8DjrJUvlOKdP8TNruy1yEaDfgpAIgbSAN7pye4FEHg9tYQ== + dependencies: + envinfo "^7.7.3" + +"@webpack-cli/serve@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.1.0.tgz#13ad38f89b6e53d1133bac0006a128217a6ebf92" + integrity sha512-7RfnMXCpJ/NThrhq4gYQYILB18xWyoQcBey81oIyVbmgbc6m5ZHHyFK+DyH7pLHJf0p14MxL4mTsoPAgBSTpIg== + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -1280,9 +1268,9 @@ accepts@~1.3.4: negotiator "0.6.2" acorn-jsx@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" - integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== + version "5.3.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== acorn@5.X, acorn@^5.0.3: version "5.7.4" @@ -1290,14 +1278,14 @@ acorn@5.X, acorn@^5.0.3: integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== acorn@^6.4.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" - integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== + version "6.4.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== acorn@^7.4.0: - version "7.4.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" - integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== acorn@^8.0.4: version "8.0.4" @@ -1310,9 +1298,9 @@ after@0.8.2: integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= aggregate-error@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" - integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== dependencies: clean-stack "^2.0.0" indent-string "^4.0.0" @@ -1327,7 +1315,7 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.5.5: +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1409,11 +1397,10 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: color-convert "^1.9.0" ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" - integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: - "@types/color-name" "^1.1.1" color-convert "^2.0.1" ansi-wrap@0.1.0, ansi-wrap@^0.1.0: @@ -1455,9 +1442,9 @@ aproba@^1.0.3, aproba@^1.1.1: integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== arch@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.1.tgz#8f5c2731aa35a30929221bb0640eed65175ec84e" - integrity sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg== + version "2.2.0" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" + integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== archive-type@^4.0.0: version "4.0.0" @@ -1515,6 +1502,11 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +array-back@^4.0.0, array-back@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.1.tgz#9b80312935a52062e1a233a9c7abeb5481b30e90" + integrity sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg== + array-differ@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" @@ -1613,14 +1605,15 @@ arrify@^2.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== -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== +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== dependencies: bn.js "^4.0.0" inherits "^2.0.1" minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" asn1@~0.2.3: version "0.2.4" @@ -1733,9 +1726,9 @@ aws-sign2@~0.7.0: integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" - integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== axios@0.19.0: version "0.19.0" @@ -1793,12 +1786,17 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +base64-arraybuffer@0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz#9818c79e059b1355f97e0428a017c838e90ba812" + integrity sha1-mBjHngWbE1X5fgQooBfIOOkLqBI= + base64-arraybuffer@0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg= -base64-js@^1.0.2: +base64-js@^1.0.2, base64-js@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== @@ -1945,11 +1943,16 @@ blurhash@^1.1.3: resolved "https://registry.yarnpkg.com/blurhash/-/blurhash-1.1.3.tgz#dc325af7da836d07a0861d830bdd63694382483e" integrity sha512-yUhPJvXexbqbyijCIE/T2NCXcj9iNPhWmOKbPTuR/cm7Q5snXYIfnVnz6m7MWOXxODMz/Cr3UcVkRdHiuDVRDw== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0: version "4.11.9" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== +bn.js@^5.1.1: + version "5.1.3" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" + integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== + boolbase@^1.0.0, boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -2080,7 +2083,7 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0: +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= @@ -2089,17 +2092,19 @@ browserify-rsa@^4.0.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= + version "4.2.1" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== 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" + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.3" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" browserify-zlib@^0.2.0: version "0.2.0" @@ -2117,14 +2122,14 @@ browserslist@^1.1.3: electron-to-chromium "^1.2.7" browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.12.2, browserslist@^4.14.5, browserslist@^4.6.4, browserslist@^4.8.5: - version "4.14.5" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.5.tgz#1c751461a102ddc60e40993639b709be7f2c4015" - integrity sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA== + version "4.14.6" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.6.tgz#97702a9c212e0c6b6afefad913d3a1538e348457" + integrity sha512-zeFYcUo85ENhc/zxHbiIp0LGzzTrE2Pv2JhxvS7kpUb9Q9D38kUX6Bie7pGutJ/5iF5rOxE7CepAuWD56xJ33A== dependencies: - caniuse-lite "^1.0.30001135" - electron-to-chromium "^1.3.571" - escalade "^3.1.0" - node-releases "^1.1.61" + caniuse-lite "^1.0.30001154" + electron-to-chromium "^1.3.585" + escalade "^3.1.1" + node-releases "^1.1.65" bs-recipes@1.3.4: version "1.3.4" @@ -2184,12 +2189,12 @@ buffer@^4.3.0: isarray "^1.0.0" buffer@^5.2.1: - version "5.6.0" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" - integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" + base64-js "^1.3.1" + ieee754 "^1.1.13" builtin-status-codes@^3.0.0: version "3.0.0" @@ -2250,6 +2255,14 @@ cacheable-request@^2.1.1: normalize-url "2.0.1" responselike "1.0.2" +call-bind@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce" + integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.0" + call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" @@ -2346,10 +2359,10 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.1.0.tgz#27dc176173725fb0adf8a48b647f4d7871944d78" - integrity sha512-WCMml9ivU60+8rEJgELlFp1gxFcEGxwYleE3bziHEDeqsqAWGHdimB7beBFGjLzVNgPGyDsfgXLQEYMpmIFnVQ== +camelcase@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" + integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== caniuse-api@^3.0.0: version "3.0.0" @@ -2361,25 +2374,15 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-db@^1.0.30000639: - version "1.0.30001036" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001036.tgz#8761fb6cd423ef2d3f8d96a21d898932252dc477" - integrity sha512-plRkihXQyiDaFUXC7x/jAIXXTKiiaWvfAagsruh/vmstnRQ+a2a95HyENxiTr5WrkPSvmFUIvsRUalVFyeh2/w== +caniuse-db@^1.0.30000639, caniuse-db@^1.0.30001090: + version "1.0.30001156" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001156.tgz#279f2188d3f7a29313ec0e7e9efb600ca9c61418" + integrity sha512-L9vmkUDqH5QWgnB3RUukW1B5P6Vvkf44pjvaoPOUbIkchkUsq+vwXjzjQl9Hw3Ri8xS3XJmfm3H0UGyTx+s+Rg== -caniuse-db@^1.0.30001090: - version "1.0.30001093" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001093.tgz#5a1cae72d94df1156f40f15d9079456e1b29d050" - integrity sha512-XqXxHR6Z9IN0BXLKMaTJ1NZ+US74cbKritholD6uaDLUWHiDj0QilpSb708wOcoGz0PmPRsXT/6zE+bjx+QSMw== - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109: - version "1.0.30001109" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001109.tgz#a9f3f26a0c3753b063d7acbb48dfb9c0e46f2b19" - integrity sha512-4JIXRodHzdS3HdK8nSgIqXYLExOvG+D2/EenSvcub2Kp3QEADjo2v2oUn5g0n0D+UNwG9BtwKOyGcSq2qvQXvQ== - -caniuse-lite@^1.0.30001135: - version "1.0.30001148" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001148.tgz#dc97c7ed918ab33bf8706ddd5e387287e015d637" - integrity sha512-E66qcd0KMKZHNJQt9hiLZGE3J4zuTqE1OnU53miEVtylFbwOEmeA5OsRu90noZful+XGSQOni1aT2tiqu/9yYw== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001154: + version "1.0.30001156" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001156.tgz#75c20937b6012fe2b02ab58b30d475bf0718de97" + integrity sha512-z7qztybA2eFZTB6Z3yvaQBIoJpQtsewRD74adw2UbRWwsRq3jIPvgrQGawBMbfafekQaD21FWuXNcywtTDGGCw== caseless@~0.12.0: version "0.12.0" @@ -2397,9 +2400,9 @@ caw@^2.0.0, caw@^2.0.1: url-to-options "^1.0.1" ccount@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.5.tgz#ac82a944905a65ce204eb03023157edf29425c17" - integrity sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" + integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" @@ -2477,9 +2480,9 @@ chokidar@^2.0.0, chokidar@^2.1.8: fsevents "^1.2.7" chokidar@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.1.tgz#e905bdecf10eaa0a0b1db0c664481cc4cbc22ba1" - integrity sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g== + version "3.4.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" + integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== dependencies: anymatch "~3.1.1" braces "~3.0.2" @@ -2487,7 +2490,7 @@ chokidar@^3.4.1: is-binary-path "~2.1.0" is-glob "~4.0.1" normalize-path "~3.0.0" - readdirp "~3.4.0" + readdirp "~3.5.0" optionalDependencies: fsevents "~2.1.2" @@ -2542,6 +2545,14 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +clean-webpack-plugin@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz#a99d8ec34c1c628a4541567aa7b457446460c62b" + integrity sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A== + dependencies: + "@types/webpack" "^4.4.31" + del "^4.1.1" + cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" @@ -2685,10 +2696,10 @@ color-name@^1.0.0, color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-string@^1.5.2: - version "1.5.3" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" - integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== +color-string@^1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.4.tgz#dd51cd25cfee953d138fe4002372cc3d0e504cb6" + integrity sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" @@ -2699,12 +2710,12 @@ color-support@^1.1.3: integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== color@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" - integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== + version "3.1.3" + resolved "https://registry.yarnpkg.com/color/-/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e" + integrity sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ== dependencies: color-convert "^1.9.1" - color-string "^1.5.2" + color-string "^1.5.4" colorette@^1.2.1: version "1.2.1" @@ -2718,12 +2729,22 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +command-line-usage@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.0.tgz#f28376a3da3361ff3d36cfd31c3c22c9a64c7cb6" + integrity sha512-Ew1clU4pkUeo6AFVDFxCbnN7GIZfXl48HIOQeFQnkO3oOqvpI7wdqtLRwv9iOCZ/7A+z4csVZeiDdEcj8g6Wiw== + dependencies: + array-back "^4.0.0" + chalk "^2.4.2" + table-layout "^1.0.0" + typical "^5.2.0" + commander@2.17.x: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== -commander@^2.2.0, commander@^2.20.0: +commander@^2.2.0, commander@^2.20.0, commander@^2.8.1: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -2733,18 +2754,21 @@ commander@^4.1.1: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== +commander@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75" + integrity sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q== + +commander@~2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" + integrity sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA== + commander@~2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== -commander@~2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" - integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= - dependencies: - graceful-readlink ">= 1.0.0" - commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -2760,7 +2784,7 @@ component-emitter@1.2.1: resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= -component-emitter@^1.2.1: +component-emitter@^1.2.1, component-emitter@~1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== @@ -2785,7 +2809,7 @@ concat-stream@^1.5.0, concat-stream@^1.6.0: readable-stream "^2.2.2" typedarray "^0.0.6" -concat-with-sourcemaps@^1.0.0: +concat-with-sourcemaps@^1.0.0, concat-with-sourcemaps@^1.0.5: version "1.1.0" resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz#d4ea93f05ae25790951b99e7b3b09e3908a4082e" integrity sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg== @@ -2890,9 +2914,9 @@ copy-props@^2.0.1: is-plain-object "^2.0.1" copy-webpack-plugin@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz#5481a03dea1123d88a988c6ff8b78247214f0b88" - integrity sha512-P15M5ZC8dyCjQHWwd4Ia/dm0SgVvZJMYeykVIVYXbGyqO4dWB5oyPHp9i7wjwo5LhtlhKbiBCdS2NvM07Wlybg== + version "5.1.2" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.1.2.tgz#8a889e1dcafa6c91c6cd4be1ad158f1d3823bae2" + integrity sha512-Uh7crJAco3AjBvgAy9Z75CjK8IG+gxaErro71THQ+vv/bl4HaQcpkexAY8KVW/T6D2W2IRr+couF/knIRkZMIQ== dependencies: cacache "^12.0.3" find-cache-dir "^2.1.0" @@ -2904,7 +2928,7 @@ copy-webpack-plugin@^5.1.1: normalize-path "^3.0.0" p-limit "^2.2.1" schema-utils "^1.0.0" - serialize-javascript "^2.1.2" + serialize-javascript "^4.0.0" webpack-log "^2.0.0" core-js-compat@^3.6.2: @@ -2952,14 +2976,14 @@ cosmiconfig@^7.0.0: yaml "^1.10.0" 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== + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== dependencies: bn.js "^4.1.0" - elliptic "^6.0.0" + elliptic "^6.5.3" -create-hash@^1.1.0, create-hash@^1.1.2: +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== @@ -2970,7 +2994,7 @@ create-hash@^1.1.0, create-hash@^1.1.2: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: 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== @@ -3010,7 +3034,7 @@ cross-spawn@^6.0.0: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -3065,15 +3089,15 @@ css-has-pseudo@^0.10.0: postcss-selector-parser "^5.0.0-rc.4" css-loader@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.0.0.tgz#f0a48dfacc3ab9936a05ee16a09e7f313872e117" - integrity sha512-9g35eXRBgjvswyJWoqq/seWp+BOxvUl8IinVNTsUBFFxtwfEYvlmEn6ciyn0liXGbGh5HyJjPGCuobDSfqMIVg== + version "5.0.1" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.0.1.tgz#9e4de0d6636a6266a585bd0900b422c85539d25f" + integrity sha512-cXc2ti9V234cq7rJzFKhirb2L2iPy8ZjALeVJAozXYz9te3r4eqLSixNAbMDJSgJEQywqXzs8gonxaboeKqwiw== dependencies: - camelcase "^6.1.0" + camelcase "^6.2.0" cssesc "^3.0.0" icss-utils "^5.0.0" loader-utils "^2.0.0" - postcss "^8.1.1" + postcss "^8.1.4" postcss-modules-extract-imports "^3.0.0" postcss-modules-local-by-default "^4.0.0" postcss-modules-scope "^3.0.0" @@ -3122,12 +3146,12 @@ css-tree@1.0.0-alpha.37: mdn-data "2.0.4" source-map "^0.6.1" -css-tree@1.0.0-alpha.39: - version "1.0.0-alpha.39" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb" - integrity sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA== +css-tree@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0.tgz#21993fa270d742642a90409a2c0cb3ac0298adf6" + integrity sha512-CdVYz/Yuqw0VdKhXPBIgi8DO3NicJVYZNWeX9XcIuSp9ZoFT5IcleVRW07O5rMjdcx1mb+MEJPknTTEW7DdsYw== dependencies: - mdn-data "2.0.6" + mdn-data "2.0.12" source-map "^0.6.1" css-what@2.1: @@ -3136,9 +3160,9 @@ css-what@2.1: integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== css-what@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" - integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== + version "3.4.2" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" + integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ== css@2.X, css@^2.2.1: version "2.2.4" @@ -3234,11 +3258,11 @@ cssnano@^4.1.10: postcss "^7.0.0" csso@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.3.tgz#0d9985dc852c7cc2b2cacfbbe1079014d1a8e903" - integrity sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ== + version "4.1.0" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.1.0.tgz#1d31193efa99b87aa6bad6c0cef155e543d09e8b" + integrity sha512-h+6w/W1WqXaJA4tb1dk7r5tVbOm97MsKxzwnvOR04UQ6GILroryjMWu3pmCCtL2mLaEStQ0fZgeGiy99mo7iyg== dependencies: - css-tree "1.0.0-alpha.39" + css-tree "^1.0.0" currently-unhandled@^0.4.1: version "0.4.1" @@ -3300,7 +3324,7 @@ debug@3.X: dependencies: ms "^2.1.1" -debug@4.1.1, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@~4.1.0: +debug@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -3314,6 +3338,13 @@ debug@=3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" +debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + dependencies: + ms "2.1.2" + decamelize-keys@^1.0.0, decamelize-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" @@ -3392,6 +3423,11 @@ decompress@^4.0.0, decompress@^4.2.0: pify "^2.3.0" strip-dirs "^2.0.0" +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== + deep-is@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -3438,6 +3474,19 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +del@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" + integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== + dependencies: + "@types/glob" "^7.1.1" + globby "^6.1.0" + is-path-cwd "^2.0.0" + is-path-in-cwd "^2.0.0" + p-map "^2.0.0" + pify "^4.0.1" + rimraf "^2.6.3" + del@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" @@ -3504,6 +3553,14 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" +dir-glob@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" + integrity sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag== + dependencies: + arrify "^1.0.1" + path-type "^3.0.0" + dir-glob@^2.0.0, dir-glob@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" @@ -3553,10 +3610,19 @@ dom-serializer@0: domelementtype "^2.0.1" entities "^2.0.0" +dom-serializer@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.1.0.tgz#5f7c828f1bfc44887dc2a315ab5c45691d544b58" + integrity sha512-ox7bvGXt2n+uLWtCRLybYx60IrOlWL/aCebWJk1T0d4m3y2tzf4U3ij9wBMUb6YJZpz06HCCYuyCDveE2xXmzQ== + dependencies: + domelementtype "^2.0.1" + domhandler "^3.0.0" + entities "^2.0.0" + dom7@^3.0.0-alpha.7: - version "3.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/dom7/-/dom7-3.0.0-alpha.7.tgz#3b4ba156a83fa37fb3fa34b8ab40a1a41a56feb1" - integrity sha512-3epkQPsKsbk2Dixqqgm2DT/KzhiAPByjDK7emu6owwFLbM5UoiqWKgdsH+6PpMEgoeR6Ex/bW1UbOe0FWZU0zg== + version "3.0.0-alpha.9" + resolved "https://registry.yarnpkg.com/dom7/-/dom7-3.0.0-alpha.9.tgz#0110c21181b8bad3a1ee72443e04d3c2e3f1d38f" + integrity sha512-wTxPe1vJqLAy2PzAROh/n1PsRF/ZklAJyRIn9shm2dAQjP4JhjsgDKQ1YTbuzf1KVlqOlqYPmwupQExcB9jOUg== dependencies: ssr-window "^3.0.0-alpha.1" @@ -3571,9 +3637,9 @@ domelementtype@1, domelementtype@^1.3.1: integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== domelementtype@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" - integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + version "2.0.2" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.2.tgz#f3b6e549201e46f588b59463dd77187131fe6971" + integrity sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA== domhandler@^2.3.0: version "2.4.2" @@ -3582,6 +3648,13 @@ domhandler@^2.3.0: dependencies: domelementtype "1" +domhandler@^3.0.0, domhandler@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.3.0.tgz#6db7ea46e4617eb15cf875df68b2b8524ce0037a" + integrity sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA== + dependencies: + domelementtype "^2.0.1" + domutils@1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" @@ -3598,6 +3671,15 @@ domutils@^1.5.1, domutils@^1.7.0: dom-serializer "0" domelementtype "1" +domutils@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.4.2.tgz#7ee5be261944e1ad487d9aa0616720010123922b" + integrity sha512-NKbgaM8ZJOecTZsIzW5gSuplsX2IWW2mIK7xVr8hTQF2v1CJWTmLZ1HOCh5sH+IzVPAGE5IucooOkvwBRAdowA== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.0.1" + domhandler "^3.3.0" + dot-case@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.3.tgz#21d3b52efaaba2ea5fda875bb1aa8124521cf4aa" @@ -3607,9 +3689,9 @@ dot-case@^3.0.3: tslib "^1.10.0" dot-prop@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" - integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== + version "5.3.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== dependencies: is-obj "^2.0.0" @@ -3661,9 +3743,9 @@ duplexer3@^0.1.4: integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= duplexer@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" @@ -3720,17 +3802,12 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.2.7: - version "1.3.427" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.427.tgz#ea43d02908a8c71f47ebb46e09de5a3cf8236f04" - integrity sha512-/rG5G7Opcw68/Yrb4qYkz07h3bESVRJjUl4X/FrKLXzoUJleKm6D7K7rTTz8V5LUWnd+BbTOyxJX2XprRqHD8A== +electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.585: + version "1.3.589" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.589.tgz#bd26183ed8697dde6ac19acbc16a3bf33b1f8220" + integrity sha512-rQItBTFnol20HaaLm26UgSUduX7iGerwW7pEYX17MB1tI6LzFajiLV7iZ7LVcUcsN/7HrZUoCLrBauChy/IqEg== -electron-to-chromium@^1.3.571: - version "1.3.578" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.578.tgz#e6671936f4571a874eb26e2e833aa0b2c0b776e0" - integrity sha512-z4gU6dA1CbBJsAErW5swTGAaU2TBzc2mPAonJb00zqW1rOraDo2zfBMDRvaz9cVic+0JEZiYbHWPw/fTaZlG2Q== - -elliptic@^6.0.0: +elliptic@^6.5.3: version "6.5.3" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== @@ -3788,18 +3865,18 @@ engine.io-client@~3.2.0: yeast "0.1.2" engine.io-client@~3.4.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.4.1.tgz#922ddb47eecdcb541136a93aeead24718fd05461" - integrity sha512-RJNmA+A9Js+8Aoq815xpGAsgWH1VoSYM//2VgIiu9lNOaHFfLpTjH4tOzktBpjIs5lvOfiNY1dwf+NuU6D38Mw== + version "3.4.4" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.4.4.tgz#77d8003f502b0782dd792b073a4d2cf7ca5ab967" + integrity sha512-iU4CRr38Fecj8HoZEnFtm2EiKGbYZcPn3cHxqNGl/tmdWRf60KhK+9vE0JeSjgnlS/0oynEfLgKbT9ALpim0sQ== dependencies: - component-emitter "1.2.1" + component-emitter "~1.3.0" component-inherit "0.0.3" - debug "~4.1.0" + debug "~3.1.0" engine.io-parser "~2.2.0" has-cors "1.1.0" indexof "0.0.1" - parseqs "0.0.5" - parseuri "0.0.5" + parseqs "0.0.6" + parseuri "0.0.6" ws "~6.1.0" xmlhttprequest-ssl "~1.5.4" yeast "0.1.2" @@ -3816,13 +3893,13 @@ engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: has-binary2 "~1.0.2" engine.io-parser@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.0.tgz#312c4894f57d52a02b420868da7b5c1c84af80ed" - integrity sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w== + version "2.2.1" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.1.tgz#57ce5611d9370ee94f99641b589f94c97e4f5da7" + integrity sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg== dependencies: after "0.8.2" arraybuffer.slice "~0.0.7" - base64-arraybuffer "0.1.5" + base64-arraybuffer "0.1.4" blob "0.0.5" has-binary2 "~1.0.2" @@ -3855,7 +3932,7 @@ enhanced-resolve@^5.3.1: graceful-fs "^4.2.4" tapable "^2.0.0" -enquirer@^2.3.5: +enquirer@^2.3.5, enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -3868,15 +3945,20 @@ entities@^1.1.1: integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" - integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + version "2.1.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" + integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== env-paths@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== +envinfo@^7.7.3: + version "7.7.3" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.7.3.tgz#4b2d8622e3e7366afb8091b23ed95569ea0208cc" + integrity sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA== + epubjs@^0.3.85: version "0.3.88" resolved "https://registry.yarnpkg.com/epubjs/-/epubjs-0.3.88.tgz#bc365e7e21893cf2d92717ce10927c1071275347" @@ -3906,39 +3988,40 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.5: - version "1.17.6" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" - integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== +es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2: + version "1.17.7" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" + integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.1" - is-callable "^1.2.0" - is-regex "^1.1.0" - object-inspect "^1.7.0" + is-callable "^1.2.2" + is-regex "^1.1.1" + object-inspect "^1.8.0" object-keys "^1.1.1" - object.assign "^4.1.0" + object.assign "^4.1.1" string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" -es-abstract@^1.17.2: - version "1.17.5" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" - integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg== +es-abstract@^1.18.0-next.1: + version "1.18.0-next.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" + integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.1" - is-callable "^1.1.5" - is-regex "^1.0.5" - object-inspect "^1.7.0" + is-callable "^1.2.2" + is-negative-zero "^2.0.0" + is-regex "^1.1.1" + object-inspect "^1.8.0" object-keys "^1.1.1" - object.assign "^4.1.0" - string.prototype.trimleft "^2.1.1" - string.prototype.trimright "^2.1.1" + object.assign "^4.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" es-to-primitive@^1.2.1: version "1.2.1" @@ -3990,10 +4073,10 @@ es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: es6-iterator "^2.0.3" es6-symbol "^3.1.1" -escalade@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.0.tgz#e8e2d7c7a8b76f6ee64c2181d6b8151441602d4e" - integrity sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig== +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-html@~1.0.3: version "1.0.3" @@ -4182,31 +4265,19 @@ esquery@^1.2.0: dependencies: estraverse "^5.1.0" -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" - -esrecurse@^4.3.0: +esrecurse@^4.1.0, esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: estraverse "^5.2.0" -estraverse@^4.1.0, estraverse@^4.1.1: +estraverse@^4.1.1: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -estraverse@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642" - integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw== - -estraverse@^5.2.0: +estraverse@^5.1.0, estraverse@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== @@ -4230,9 +4301,9 @@ event-emitter@^0.3.5: es5-ext "~0.10.14" eventemitter3@^4.0.0, eventemitter3@^4.0.3: - version "4.0.4" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" - integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== events@^3.0.0, events@^3.2.0: version "3.2.0" @@ -4284,6 +4355,21 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^4.0.0, execa@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + execall@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execall/-/execall-1.0.0.tgz#73d0904e395b3cab0658b08d09ec25307f29bb73" @@ -4406,7 +4492,7 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^2.2.6: +fast-glob@^2.0.2, fast-glob@^2.2.6: version "2.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== @@ -4435,6 +4521,11 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-levenshtein@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz#e6a754cc8f15e58987aa9cbd27af66fd6f4e5af9" + integrity sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk= + fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -4451,9 +4542,9 @@ fastest-levenshtein@^1.0.12: integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== fastq@^1.6.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.7.0.tgz#fcd79a08c5bd7ec5b55cd3f5c4720db551929801" - integrity sha512-YOadQRnHd5q6PogvAR/x62BGituF2ufiEA6s8aavQANw5YKHERI4AREboX6KotzP8oX2klxYF2wcV/7bn1clfQ== + version "1.9.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.9.0.tgz#e16a72f338eaca48e91b5c23593bcc2ef66b7947" + integrity sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w== dependencies: reusify "^1.0.4" @@ -4708,9 +4799,9 @@ follow-redirects@1.5.10: debug "=3.1.0" follow-redirects@^1.0.0: - version "1.12.1" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.12.1.tgz#de54a6205311b93d60398ebc01cf7015682312b6" - integrity sha512-tmRv0AVuR7ZyouUHLeNSiO6pqulF7dYa3s19c6t+wz9LD69/uSzdMxJ2S91nTI9U3rt/IldxpzMOFejp6f0hjg== + version "1.13.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" + integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" @@ -4808,9 +4899,9 @@ fs.realpath@^1.0.0: integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^1.2.7: - version "1.2.12" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.12.tgz#db7e0d8ec3b0b45724fd4d83d43554a8f1f0de5c" - integrity sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q== + version "1.2.13" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== dependencies: bindings "^1.5.0" nan "^2.12.1" @@ -4867,9 +4958,9 @@ gaze@^1.0.0: globule "^1.0.0" gensync@^1.0.0-beta.1: - version "1.0.0-beta.1" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" - integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-caller-file@^1.0.1: version "1.0.3" @@ -4881,6 +4972,15 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-intrinsic@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be" + integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-proxy@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93" @@ -4923,6 +5023,13 @@ get-stream@^4.0.0: dependencies: pump "^3.0.0" +get-stream@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + 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" @@ -4943,13 +5050,13 @@ getpass@^0.1.1: assert-plus "^1.0.0" gifsicle@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/gifsicle/-/gifsicle-5.0.0.tgz#d1ca7f223e949966d373eb1fb6e7ce156d257750" - integrity sha512-GZ1ym4uY12FHXsf26Kk1G06Edwago9zctqUqin69pm8ObA13jb3urgHU9PgKmtH6kHaCjEcjoRzNjxUyYvb1Bg== + version "5.1.0" + resolved "https://registry.yarnpkg.com/gifsicle/-/gifsicle-5.1.0.tgz#08f878e9048c70adf046185115a6350516a1fdc0" + integrity sha512-hQsOH7yjC7fMokntysN6f2QuxrnX+zmKKKVy0sC3Vhtnk8WrOxLdfH/Z2PNn7lVVx+1+drzIeAe8ufcmdSC/8g== dependencies: bin-build "^3.0.0" bin-wrapper "^4.0.0" - execa "^1.0.0" + execa "^4.0.0" logalot "^2.0.0" glob-parent@^3.1.0: @@ -4994,15 +5101,16 @@ glob-to-regexp@^0.4.1: integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== glob-watcher@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-5.0.3.tgz#88a8abf1c4d131eb93928994bc4a593c2e5dd626" - integrity sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg== + version "5.0.5" + resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-5.0.5.tgz#aa6bce648332924d9a8489be41e3e5c52d4186dc" + integrity sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw== dependencies: anymatch "^2.0.0" async-done "^1.2.0" chokidar "^2.0.0" is-negated-glob "^1.0.0" just-debounce "^1.0.0" + normalize-path "^3.0.0" object.defaults "^1.1.0" glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1: @@ -5091,6 +5199,17 @@ globby@^11.0.1: merge2 "^1.3.0" slash "^3.0.0" +globby@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" + integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= + dependencies: + array-union "^1.0.1" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + globby@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" @@ -5103,6 +5222,19 @@ globby@^7.1.1: pify "^3.0.0" slash "^1.0.0" +globby@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.2.tgz#5697619ccd95c5275dbb2d6faa42087c1a941d8d" + integrity sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w== + dependencies: + array-union "^1.0.1" + dir-glob "2.0.0" + fast-glob "^2.0.2" + glob "^7.1.2" + ignore "^3.3.5" + pify "^3.0.0" + slash "^1.0.0" + globby@^9.0.0: version "9.2.0" resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" @@ -5123,12 +5255,12 @@ globjoin@^0.1.4: integrity sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM= globule@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.1.tgz#90a25338f22b7fbeb527cee63c629aea754d33b9" - integrity sha512-OVyWOHgw29yosRHCHo7NncwR1hW5ew0W/UrvtwvjefVJeQ26q4/8r8FmPsSF1hJ93IgWkyv16pCTz6WblMzm/g== + version "1.3.2" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.2.tgz#d8bdd9e9e4eef8f96e245999a5dee7eb5d8529c4" + integrity sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA== dependencies: glob "~7.1.1" - lodash "~4.17.12" + lodash "~4.17.10" minimatch "~3.0.2" glogg@^1.0.0: @@ -5138,14 +5270,7 @@ glogg@^1.0.0: dependencies: sparkles "^1.0.0" -gonzales-pe@^4.2.3: - version "4.2.4" - resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.4.tgz#356ae36a312c46fe0f1026dd6cb539039f8500d2" - integrity sha512-v0Ts/8IsSbh9n1OJRnSfa7Nlxi4AkXIsWB6vPept8FDbL4bXn3FNuxjYtO/nmBGu7GDkL9MFeGebeSu6l55EPQ== - dependencies: - minimist "1.1.x" - -gonzales-pe@^4.3.0: +gonzales-pe@^4.2.3, gonzales-pe@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.3.0.tgz#fe9dec5f3c557eead09ff868c65826be54d067b3" integrity sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ== @@ -5200,11 +5325,6 @@ graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.10, graceful-fs@^4.1.11, g resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= - group-array@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/group-array/-/group-array-1.0.0.tgz#e2e8d8890e5b46f72eb49b71e8af675173a9d0f7" @@ -5424,11 +5544,11 @@ har-schema@^2.0.0: integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== dependencies: - ajv "^6.5.5" + ajv "^6.12.3" har-schema "^2.0.0" hard-rejection@^2.1.0: @@ -5482,7 +5602,7 @@ has-symbol-support-x@^1.4.1: resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== -has-symbols@^1.0.0, has-symbols@^1.0.1: +has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== @@ -5618,10 +5738,20 @@ html-comment-regex@^1.1.0, html-comment-regex@^1.1.2: resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== -html-minifier-terser@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.1.0.tgz#95d3df037f04835e9d1a09d1767c0e361a7de916" - integrity sha512-tiYE76O1zunboByeB/nFGwUEb263Z3nkNv6Lz2oLC1s6M36bLKfTrjQ+7ssVfaucVllE+N7hh/FbpbxvnIA+LQ== +html-loader@^1.1.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-1.3.2.tgz#5a72ebba420d337083497c9aba7866c9e1aee340" + integrity sha512-DEkUwSd0sijK5PF3kRWspYi56XP7bTNkyg5YWSzBdjaSDmvCufep5c4Vpb3PBf6lUL0YPtLwBfy9fL0t5hBAGA== + dependencies: + html-minifier-terser "^5.1.1" + htmlparser2 "^4.1.0" + loader-utils "^2.0.0" + schema-utils "^3.0.0" + +html-minifier-terser@^5.0.1, html-minifier-terser@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#922e96f1f3bb60832c2634b79884096389b1f054" + integrity sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg== dependencies: camel-case "^4.1.1" clean-css "^4.2.3" @@ -5681,6 +5811,16 @@ htmlparser2@^3.10.0, htmlparser2@^3.3.0: inherits "^2.0.1" readable-stream "^3.1.1" +htmlparser2@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78" + integrity sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q== + dependencies: + domelementtype "^2.0.1" + domhandler "^3.0.0" + domutils "^2.0.0" + entities "^2.0.0" + http-cache-semantics@3.8.1: version "3.8.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" @@ -5730,6 +5870,11 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -5742,10 +5887,10 @@ icss-utils@^5.0.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.0.0.tgz#03ed56c3accd32f9caaf1752ebf64ef12347bb84" integrity sha512-aF2Cf/CkEZrI/vsu5WI/I+akFgdbwQHVE9YRZxATrhH4PVIe6a3BIjwjEcW+z+jP/hNh+YvM3lAAn1wJQ6opSg== -ieee754@^1.1.4: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== +ieee754@^1.1.13, ieee754@^1.1.4: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== iferr@^0.1.5: version "0.1.5" @@ -5841,9 +5986,9 @@ import-fresh@^2.0.0: resolve-from "^3.0.0" import-fresh@^3.0.0, import-fresh@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" - integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + version "3.2.2" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.2.tgz#fc129c160c5d68235507f4331a6baad186bdbc3e" + integrity sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" @@ -5865,6 +6010,14 @@ import-lazy@^4.0.0: resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== +import-local@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" + integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -5940,6 +6093,11 @@ interpret@^1.4.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== +interpret@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" + integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + intersection-observer@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/intersection-observer/-/intersection-observer-0.11.0.tgz#f4ea067070326f68393ee161cc0a2ca4c0040c6f" @@ -6043,14 +6201,14 @@ is-buffer@^1.1.5: integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-buffer@^2.0.0, is-buffer@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" - integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== -is-callable@^1.1.4, is-callable@^1.1.5, is-callable@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" - integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== +is-callable@^1.1.4, is-callable@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" + integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== is-color-stop@^1.0.0: version "1.1.0" @@ -6064,6 +6222,13 @@ is-color-stop@^1.0.0: rgb-regex "^1.0.1" rgba-regex "^1.0.0" +is-core-module@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz#a4cc031d9b1aca63eecbd18a650e13cb4eeab946" + integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA== + dependencies: + has "^1.0.3" + 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" @@ -6083,7 +6248,7 @@ is-date-object@^1.0.1: resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== -is-decimal@^1.0.0, is-decimal@^1.0.2: +is-decimal@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== @@ -6191,6 +6356,11 @@ is-negated-glob@^1.0.0: resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= +is-negative-zero@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" + integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= + is-number-like@^1.0.3: version "1.0.8" resolved "https://registry.yarnpkg.com/is-number-like/-/is-number-like-1.0.8.tgz#2e129620b50891042e44e9bbbb30593e75cfbbe3" @@ -6225,11 +6395,25 @@ is-object@^1.0.1: resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= -is-path-cwd@^2.2.0: +is-path-cwd@^2.0.0, is-path-cwd@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== +is-path-in-cwd@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" + integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== + dependencies: + is-path-inside "^2.1.0" + +is-path-inside@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" + integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== + dependencies: + path-is-inside "^1.0.2" + is-path-inside@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" @@ -6267,10 +6451,10 @@ is-promise@^4.0.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ== -is-regex@^1.0.5, is-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" - integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw== +is-regex@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== dependencies: has-symbols "^1.0.1" @@ -6306,6 +6490,11 @@ is-stream@^1.0.0, is-stream@^1.1.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + is-string@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" @@ -6430,9 +6619,9 @@ jellyfin-apiclient@^1.4.2: integrity sha512-xUvt1G0cDlam6hJgC5Jr6EE5botzdEMGxeer3Vm0+zhM7nb8iFnRmQRmTpVbXtYS8NLiHsiUmK1RLlelgtWDYg== jest-worker@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.1.tgz#c2ae8cde6802cc14056043f997469ec170d9c32a" - integrity sha512-R5IE3qSGz+QynJx8y+ICEkdI2OJ3RJjRQVEyCcFAd3yVhQSEtquziPO29Mlzgn07LOVE8u8jhJ1FqcwegiXWOw== + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" + integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== dependencies: "@types/node" "*" merge-stream "^2.0.0" @@ -6444,9 +6633,9 @@ jquery@>=1.9.1, jquery@^3.5.1: integrity sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg== js-base64@^2.1.8, js-base64@^2.1.9: - version "2.5.2" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.2.tgz#313b6274dda718f714d00b3330bbae6e38e90209" - integrity sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ== + version "2.6.4" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4" + integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ== js-tokens@^4.0.0: version "4.0.0" @@ -6486,6 +6675,11 @@ json-parse-better-errors@^1.0.1, json-parse-better-errors@^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-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + 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" @@ -6646,6 +6840,11 @@ leven@^2.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -6769,9 +6968,9 @@ loader-utils@^2.0.0: json5 "^2.1.2" localforage@*, localforage@^1.7.3: - version "1.7.4" - resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.7.4.tgz#88b59cc9b25ae54c76bb2c080b21ec832c22d3f6" - integrity sha512-3EmVZatmNVeCo/t6Te7P06h2alGwbq8wXlSkcSXMvDE2/edPmsVqTPlzGnZaqwZZDBs6v+kxWpqjVsqsNJT8jA== + version "1.9.0" + resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.9.0.tgz#f3e4d32a8300b362b4634cc4e066d9d00d2f09d1" + integrity sha512-rR1oyNrKulpe+VM9cYmcFn6tsHuokyVHFaCM3+osEmxaHTbEk8oQu6eGDfS6DQLWi/N67XRmB8ECG37OES368g== dependencies: lie "3.1.1" @@ -6947,7 +7146,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.0.0, lodash@^4.1.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@~4.17.12: +lodash@^4.0.0, lodash@^4.1.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@~4.17.10: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -7175,22 +7374,22 @@ mdast-util-compact@^2.0.0: unist-util-visit "^2.0.0" mdn-browser-compat-data@^1.0.28: - version "1.0.29" - resolved "https://registry.yarnpkg.com/mdn-browser-compat-data/-/mdn-browser-compat-data-1.0.29.tgz#9edddaa953221050c6959a538c993e915e619220" - integrity sha512-R9/8Xi1d9by2Ag5O7Sur3zoe8k/61a+yYeC4f6S5UhbEZb2ICmYNZuprm+2IO9bBcT3Pa2BtEx+xKoX/8v8tPw== + version "1.1.2" + resolved "https://registry.yarnpkg.com/mdn-browser-compat-data/-/mdn-browser-compat-data-1.1.2.tgz#90d2a25ce731b34a14329396887dadfd657ea7b2" + integrity sha512-uBNX2P4iu3PZcXP20rL+n7fxN9PWZLj0y43QMe/1aXzqP3H6HbVOeePS0cBZCtMwcfr2Tugf1OHj+/wLam+dUg== dependencies: extend "3.0.2" +mdn-data@2.0.12: + version "2.0.12" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.12.tgz#bbb658d08b38f574bbb88f7b83703defdcc46844" + integrity sha512-ULbAlgzVb8IqZ0Hsxm6hHSlQl3Jckst2YEQS7fODu9ilNWy2LvcoSY7TRFIktABP2mdppBioc66va90T+NUs8Q== + mdn-data@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== -mdn-data@2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.6.tgz#852dc60fcaa5daa2e8cf6c9189c440ed3e042978" - integrity sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA== - memoizee@0.4.X: version "0.4.14" resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57" @@ -7275,9 +7474,9 @@ merge-stream@^2.0.0: integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== merge2@^1.2.3, merge2@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" - integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" @@ -7314,11 +7513,16 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.44.0, mime-db@^1.28.0: +mime-db@1.44.0: version "1.44.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== +mime-db@^1.28.0: + version "1.45.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" + integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== + mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.27" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" @@ -7331,15 +7535,20 @@ mime@1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + mimic-response@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== min-indent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.0.tgz#cfc45c37e9ec0d8f0a0ec3dd4ef7f7c3abe39256" - integrity sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY= + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" @@ -7375,11 +7584,6 @@ minimist-options@^3.0.1: arrify "^1.0.1" is-plain-obj "^1.1.0" -minimist@1.1.x: - version "1.1.3" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8" - integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag= - minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" @@ -7467,7 +7671,7 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@^2.1.1: +ms@2.1.2, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -7485,14 +7689,14 @@ mute-stdout@^1.0.0: integrity sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg== nan@^2.12.1, nan@^2.13.2: - version "2.14.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" - integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== + version "2.14.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" + integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== -nanoid@^3.1.12: - version "3.1.12" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654" - integrity sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A== +nanoid@^3.1.16: + version "3.1.16" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.16.tgz#b21f0a7d031196faf75314d7c65d36352beeef64" + integrity sha512-+AK8MN0WHji40lj8AEuwLOvLSbWYApQpre/aFJZD71r43wVRLrOYS4FmJOPQYon1TqB462RzrrxlfA74XRES8w== nanomatch@^1.2.9: version "1.2.13" @@ -7624,15 +7828,15 @@ node-libs-browser@^2.2.1: util "^0.11.0" vm-browserify "^1.0.1" -node-releases@^1.1.61: - version "1.1.61" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.61.tgz#707b0fca9ce4e11783612ba4a2fcba09047af16e" - integrity sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g== +node-releases@^1.1.65: + version "1.1.65" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.65.tgz#52d9579176bd60f23eba05c4438583f341944b81" + integrity sha512-YpzJOe2WFIW0V4ZkJQd/DGR/zdVwc/pI4Nl1CZrBO19FdRcSTmsuhdttw9rsTzzJLrNcSloLiBbEYx1C4f6gpA== node-sass@^4.8.3: - version "4.14.0" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.14.0.tgz#a8e9d7720f8e15b4a1072719dcf04006f5648eeb" - integrity sha512-AxqU+DFpk0lEz95sI6jO0hU0Rwyw7BXVEv6o9OItoXLyeygPeaSpiV4rwQb10JiTghHaa0gZeD21sz+OsQluaw== + version "4.14.1" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5" + integrity sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g== dependencies: async-foreach "^0.1.3" chalk "^1.1.1" @@ -7648,7 +7852,7 @@ node-sass@^4.8.3: node-gyp "^3.8.0" npmlog "^4.0.0" request "^2.88.0" - sass-graph "^2.2.4" + sass-graph "2.2.5" stdout-stream "^1.4.0" "true-case-path" "^1.0.2" @@ -7756,6 +7960,13 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" +npm-run-path@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + "npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" @@ -7812,12 +8023,12 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.7.0: +object-inspect@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -7829,15 +8040,15 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.0.4, object.assign@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== +object.assign@^4.0.4, object.assign@^4.1.0, object.assign@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" object.defaults@^1.0.0, object.defaults@^1.1.0: version "1.1.0" @@ -7904,6 +8115,13 @@ once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: dependencies: wrappy "1" +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + openurl@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/openurl/-/openurl-1.1.1.tgz#3875b4b0ef7a52c156f0db41d4609dbb0f94b387" @@ -8064,6 +8282,11 @@ p-map-series@^1.0.0: dependencies: p-reduce "^1.0.0" +p-map@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== + p-map@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" @@ -8072,9 +8295,9 @@ p-map@^4.0.0: aggregate-error "^3.0.0" p-pipe@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-3.0.0.tgz#ab1fb87c0b8dd79b3bb03a8a23680fc9d054e132" - integrity sha512-gwwdRFmaxsT3IU+Tl3vYKVRdjfhg8Bbdjw7B+E0y6F7Yz6l+eaQLn0BRmGMXIhcPDONPtOkMoNwx1etZh4zPJA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-3.1.0.tgz#48b57c922aa2e1af6a6404cb7c6bf0eb9cc8e60e" + integrity sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw== p-reduce@^1.0.0: version "1.0.0" @@ -8148,14 +8371,13 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-asn1@^5.0.0: - version "5.1.5" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" - integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== dependencies: - asn1.js "^4.0.0" + asn1.js "^5.2.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" @@ -8209,13 +8431,13 @@ parse-json@^4.0.0: json-parse-better-errors "^1.0.1" parse-json@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" - integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + version "5.1.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.1.0.tgz#f96088cdf24a8faa9aea9a009f2d9d942c999646" + integrity sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ== dependencies: "@babel/code-frame" "^7.0.0" error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" + json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" parse-node-version@^1.0.0: @@ -8235,6 +8457,11 @@ parseqs@0.0.5: dependencies: better-assert "~1.0.0" +parseqs@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.6.tgz#8e4bb5a19d1cdc844a08ac974d34e273afa670d5" + integrity sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w== + parseuri@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" @@ -8242,6 +8469,11 @@ parseuri@0.0.5: dependencies: better-assert "~1.0.0" +parseuri@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.6.tgz#e1496e829e3ac2ff47f39a4dd044b32823c4a25a" + integrity sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow== + parseurl@~1.3.2: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -8292,12 +8524,17 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + 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= -path-key@^3.1.0: +path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== @@ -8360,9 +8597,9 @@ path-webpack@0.0.3: integrity sha1-/23sdJ7sWpRgXATV9j/FVgegOhY= 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== + version "3.1.1" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" + integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -8484,9 +8721,9 @@ postcss-attribute-case-insensitive@^4.0.1: postcss-selector-parser "^6.0.2" postcss-calc@^7.0.1: - version "7.0.2" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.2.tgz#504efcd008ca0273120568b0792b16cdcde8aac1" - integrity sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ== + version "7.0.5" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.5.tgz#f8a6e99f12e619c2ebc23cf6c486fdc15860933e" + integrity sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg== dependencies: postcss "^7.0.27" postcss-selector-parser "^6.0.2" @@ -8643,9 +8880,9 @@ postcss-focus-within@^3.0.0: postcss "^7.0.2" postcss-font-variant@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz#71dd3c6c10a0d846c5eda07803439617bbbabacc" - integrity sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg== + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.1.tgz#42d4c0ab30894f60f98b17561eb5c0321f502641" + integrity sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA== dependencies: postcss "^7.0.2" @@ -8703,9 +8940,9 @@ postcss-less@^3.1.0, postcss-less@^3.1.4: postcss "^7.0.14" postcss-load-config@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.0.tgz#c84d692b7bb7b41ddced94ee62e8ab31b417b003" - integrity sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q== + version "2.1.2" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.2.tgz#c5ea504f2c4aef33c7359a34de3573772ad7502a" + integrity sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw== dependencies: cosmiconfig "^5.0.0" import-cwd "^2.0.0" @@ -9132,16 +9369,7 @@ postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: indexes-of "^1.0.1" uniq "^1.0.1" -postcss-selector-parser@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" - integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== - dependencies: - cssesc "^3.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-selector-parser@^6.0.4: +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3" integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw== @@ -9221,22 +9449,22 @@ postcss@^5.0.0, postcss@^5.0.18: supports-color "^3.2.3" postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.13, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.31, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6, postcss@^7.0.7: - version "7.0.32" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" - integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== + version "7.0.35" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" + integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== dependencies: chalk "^2.4.2" source-map "^0.6.1" supports-color "^6.1.0" -postcss@^8.1.1: - version "8.1.2" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.2.tgz#9731fcaa4f7b0bef47121821bdae9eeb609a324c" - integrity sha512-mToqEVFq8jF9TFhlIK4HhE34zknFJuNTgqtsr60vUvrWn+9TIYugCwiV1JZRxCuOrej2jjstun1bn4Bc7/1HkA== +postcss@^8.1.4: + version "8.1.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.6.tgz#b022ba2cfb8701da234d073ed3128c5a384c35ff" + integrity sha512-JuifSl4h8dJ70SiMXKjzCxhalE6p2TnMHuq9G8ftyXj2jg6SXzqCsEuxMj9RkmJoO5D+Z9YrWunNkxqpRT02qg== dependencies: colorette "^1.2.1" line-column "^1.0.2" - nanoid "^3.1.12" + nanoid "^3.1.16" source-map "^0.6.1" prelude-ls@^1.2.1: @@ -9255,17 +9483,17 @@ prepend-http@^2.0.0: integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= pretty-bytes@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" - integrity sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg== + version "5.4.1" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.4.1.tgz#cd89f79bbcef21e3d21eb0da68ffe93f803e884b" + integrity sha512-s1Iam6Gwz3JI5Hweaz4GoCD1WUNUIyzePFy5+Js2hjwGVt2Z79wNN+ZKOZ2vB6C+Xs6njyB84Z1IthQg8d9LxA== pretty-error@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3" - integrity sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM= + version "2.1.2" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.2.tgz#be89f82d81b1c86ec8fdfbc385045882727f93b6" + integrity sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw== dependencies: - renderkid "^2.0.1" - utila "~0.4" + lodash "^4.17.20" + renderkid "^2.0.4" pretty-hrtime@^1.0.0: version "1.0.3" @@ -9389,9 +9617,9 @@ query-string@^5.0.1: strict-uri-encode "^1.0.0" query-string@^6.13.6: - version "6.13.6" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.6.tgz#e5ac7c74f2a5da43fbca0b883b4f0bafba439966" - integrity sha512-/WWZ7d9na6s2wMEGdVCVgKWE9Rt7nYyNIf7k8xmHXcesPMlEzicWo3lbYwHyA4wBktI2KrXxxZeACLbE84hvSQ== + version "6.13.7" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.7.tgz#af53802ff6ed56f3345f92d40a056f93681026ee" + integrity sha512-CsGs8ZYb39zu0WLkeOhe0NMePqgYdAuCqxOYKDR5LVCytDZYMGx3Bb+xypvQvPHVPijRXB0HZNFllCzHRe4gEA== dependencies: decode-uri-component "^0.2.0" split-on-first "^1.0.0" @@ -9565,10 +9793,10 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" -readdirp@~3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada" - integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ== +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== dependencies: picomatch "^2.2.1" @@ -9579,6 +9807,13 @@ rechoir@^0.6.2: dependencies: resolve "^1.1.6" +rechoir@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.0.tgz#32650fd52c21ab252aa5d65b19310441c7e03aca" + integrity sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q== + dependencies: + resolve "^1.9.0" + redent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" @@ -9603,6 +9838,11 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" +reduce-flatten@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" + integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== + regenerate-unicode-properties@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" @@ -9611,14 +9851,14 @@ regenerate-unicode-properties@^8.2.0: regenerate "^1.4.0" regenerate@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.1.tgz#cad92ad8e6b591773485fbe05a485caf4f457e6f" - integrity sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A== + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== regenerator-runtime@^0.13.4: - version "0.13.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" - integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== + version "0.13.7" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== regenerator-transform@^0.14.2: version "0.14.5" @@ -9691,9 +9931,9 @@ remark-parse@^6.0.0: xtend "^4.0.1" remark-parse@^8.0.0: - version "8.0.2" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-8.0.2.tgz#5999bc0b9c2e3edc038800a64ff103d0890b318b" - integrity sha512-eMI6kMRjsAGpMXXBAywJwiwAse+KNpmt+BK55Oofy4KvBZEqUDj6mWbGLJZrujoPIPPxDXzn3T9baRlpsm2jnQ== + version "8.0.3" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-8.0.3.tgz#9c62aa3b35b79a486454c690472906075f40c7e1" + integrity sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q== dependencies: ccount "^1.0.0" collapse-white-space "^1.0.2" @@ -9733,9 +9973,9 @@ remark-stringify@^6.0.0: xtend "^4.0.1" remark-stringify@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-8.0.0.tgz#33423ab8bf3076fb197f4cf582aaaf866b531625" - integrity sha512-cABVYVloFH+2ZI5bdqzoOmemcz/ZuhQSH6W6ZNYnLojAUUn3xtX7u+6BpnYp35qHoGr2NFBsERV14t4vCIeW8w== + version "8.1.1" + resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-8.1.1.tgz#e2a9dc7a7bf44e46a155ec78996db896780d8ce5" + integrity sha512-q4EyPZT3PcA3Eq7vPpT6bIdokXzFGp9i85igjmhRyXWmPs0Y6/d2FYwUNotKAWyLch7g0ASZJn/KHHcHZQ163A== dependencies: ccount "^1.0.0" is-alphanumeric "^1.0.0" @@ -9762,9 +10002,9 @@ remark@^10.0.1: unified "^7.0.0" remark@^12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/remark/-/remark-12.0.0.tgz#d1c145c07341c9232f93b2f8539d56da15a2548c" - integrity sha512-oX4lMIS0csgk8AEbzY0h2jdR0ngiCHOpwwpxjmRa5TqAkeknY+tkhjRJGZqnCmvyuWh55/0SW5WY3R3nn3PH9A== + version "12.0.1" + resolved "https://registry.yarnpkg.com/remark/-/remark-12.0.1.tgz#f1ddf68db7be71ca2bad0a33cd3678b86b9c709f" + integrity sha512-gS7HDonkdIaHmmP/+shCPejCEEW+liMp/t/QwmF0Xt47Rpuhl32lLtDV1uKWvGoq+kxr5jSgg5oAIpGuyULjUw== dependencies: remark-parse "^8.0.0" remark-stringify "^8.0.0" @@ -9792,16 +10032,16 @@ remove-trailing-separator@^1.0.1, remove-trailing-separator@^1.1.0: resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= -renderkid@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.3.tgz#380179c2ff5ae1365c522bf2fcfcff01c5b74149" - integrity sha512-z8CLQp7EZBPCwCnncgf9C4XAi3WR0dv+uWu/PjIyhhAb5d6IJ/QZqlHFprHeKT+59//V6BNUsLbvN8+2LarxGA== +renderkid@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.4.tgz#d325e532afb28d3f8796ffee306be8ffd6fc864c" + integrity sha512-K2eXrSOJdq+HuKzlcjOlGoOarUu5SDguDEhE7+Ah4zuOWL40j8A/oHvLlLob9PSTNvVnBd+/q0Er1QfpEuem5g== dependencies: css-select "^1.1.0" dom-converter "^0.2" htmlparser2 "^3.3.0" + lodash "^4.17.20" strip-ansi "^3.0.0" - utila "^0.4.0" repeat-element@^1.1.2: version "1.1.3" @@ -9895,6 +10135,13 @@ resize-observer-polyfill@^1.5.1: resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.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" @@ -9930,11 +10177,12 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.4.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.9.0: + version "1.18.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.18.1.tgz#018fcb2c5b207d2a6424aee361c5a266da8f4130" + integrity sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA== dependencies: + is-core-module "^2.0.0" path-parse "^1.0.6" resp-modifier@6.0.2: @@ -10002,9 +10250,9 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: inherits "^2.0.1" run-parallel@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" - integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + version "1.1.10" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.10.tgz#60a51b2ae836636c81377df16cb107351bcd13ef" + integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw== run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" @@ -10057,21 +10305,19 @@ sass-graph@2.2.5: scss-tokenizer "^0.2.3" yargs "^13.3.2" -sass-graph@^2.2.4: - version "2.2.6" - resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.6.tgz#09fda0e4287480e3e4967b72a2d133ba09b8d827" - integrity sha512-MKuEYXFSGuRSi8FZ3A7imN1CeVn9Gpw0/SFJKdL1ejXJneI9a5rwlEZrKejhEFAA3O6yr3eIyl/WuvASvlT36g== - dependencies: - glob "^7.0.0" - lodash "^4.0.0" - scss-tokenizer "^0.2.3" - yargs "^7.0.0" - 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@^0.4.5: + version "0.4.7" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" + integrity sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ== + dependencies: + ajv "^6.1.0" + ajv-keywords "^3.1.0" + schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" @@ -10113,11 +10359,11 @@ scss-tokenizer@^0.2.3: source-map "^0.4.2" seek-bzip@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" - integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= + version "1.0.6" + resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.6.tgz#35c4171f55a680916b52a07859ecf3b5857f21c4" + integrity sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ== dependencies: - commander "~2.8.1" + commander "^2.8.1" semver-greatest-satisfied-range@^1.1.0: version "1.1.0" @@ -10182,10 +10428,12 @@ send@0.16.2: range-parser "~1.2.0" statuses "~1.4.0" -serialize-javascript@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" - integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== +serialize-javascript@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== + dependencies: + randombytes "^2.1.0" serialize-javascript@^5.0.1: version "5.0.1" @@ -10397,22 +10645,19 @@ socket.io-client@2.1.1: to-array "0.1.4" socket.io-client@^2.0.4: - version "2.3.0" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.3.0.tgz#14d5ba2e00b9bcd145ae443ab96b3f86cbcc1bb4" - integrity sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA== + version "2.3.1" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.3.1.tgz#91a4038ef4d03c19967bb3c646fec6e0eaa78cff" + integrity sha512-YXmXn3pA8abPOY//JtYxou95Ihvzmg8U6kQyolArkIyLd0pgVhrfor/iMsox8cn07WCOOvvuJ6XKegzIucPutQ== dependencies: backo2 "1.0.2" - base64-arraybuffer "0.1.5" component-bind "1.0.0" - component-emitter "1.2.1" - debug "~4.1.0" + component-emitter "~1.3.0" + debug "~3.1.0" engine.io-client "~3.4.0" has-binary2 "~1.0.2" - has-cors "1.1.0" indexof "0.0.1" - object-component "0.0.3" - parseqs "0.0.5" - parseuri "0.0.5" + parseqs "0.0.6" + parseuri "0.0.6" socket.io-parser "~3.3.0" to-array "0.1.4" @@ -10426,11 +10671,11 @@ socket.io-parser@~3.2.0: isarray "2.0.1" socket.io-parser@~3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.0.tgz#2b52a96a509fdf31440ba40fed6094c7d4f1262f" - integrity sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng== + version "3.3.1" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.1.tgz#f07d9c8cb3fb92633aa93e76d98fd3a334623199" + integrity sha512-1QLvVAe8dTz+mKmZ07Swxt+LAo4Y1ff50rlyoEx00TQmDFVQYPfcqGvIDJLGaBdhdNCecXtyKpD+EgKGcmmbuQ== dependencies: - component-emitter "1.2.1" + component-emitter "~1.3.0" debug "~3.1.0" isarray "2.0.1" @@ -10518,7 +10763,7 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@~0.7.2: +source-map@^0.7.3, source-map@~0.7.2: version "0.7.3" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== @@ -10550,9 +10795,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + version "3.0.6" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz#c80757383c28abf7296744998cbc106ae8b854ce" + integrity sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw== specificity@^0.4.1: version "0.4.1" @@ -10767,39 +11012,21 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -string.prototype.trimend@^1.0.0, string.prototype.trimend@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" - integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== +string.prototype.trimend@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz#6ddd9a8796bc714b489a3ae22246a208f37bfa46" + integrity sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw== dependencies: define-properties "^1.1.3" - es-abstract "^1.17.5" + es-abstract "^1.18.0-next.1" -string.prototype.trimleft@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc" - integrity sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw== +string.prototype.trimstart@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz#22d45da81015309cd0cdd79787e8919fc5c613e7" + integrity sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg== dependencies: define-properties "^1.1.3" - es-abstract "^1.17.5" - string.prototype.trimstart "^1.0.0" - -string.prototype.trimright@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3" - integrity sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - string.prototype.trimend "^1.0.0" - -string.prototype.trimstart@^1.0.0, string.prototype.trimstart@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" - integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" + es-abstract "^1.18.0-next.1" string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" @@ -10831,15 +11058,13 @@ stringify-entities@^1.0.1: is-hexadecimal "^1.0.0" stringify-entities@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-3.0.0.tgz#455abe501f8b7859ba5726a25a8872333c65b0a7" - integrity sha512-h7NJJIssprqlyjHT2eQt2W1F+MCcNmwPGlKb0bWEdET/3N44QN3QbUF/ueKCgAssyKRZ3Br9rQ7FcXjHr0qLHw== + version "3.1.0" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-3.1.0.tgz#b8d3feac256d9ffcc9fa1fefdcf3ca70576ee903" + integrity sha512-3FP+jGMmMV/ffZs86MoghGqAoqXAdxLrJP4GUdrDN1aIScYih5tuIO3eF4To5AJZ79KDZ8Fpdy7QJnK8SsL1Vg== dependencies: character-entities-html4 "^1.0.0" character-entities-legacy "^1.0.0" - is-alphanumerical "^1.0.0" - is-decimal "^1.0.2" - is-hexadecimal "^1.0.0" + xtend "^4.0.0" strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" @@ -10898,6 +11123,11 @@ strip-eof@^1.0.0: resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-indent@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" @@ -11194,6 +11424,16 @@ symbol-observable@1.0.1: resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" integrity sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ= +table-layout@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.1.tgz#8411181ee951278ad0638aea2f779a9ce42894f9" + integrity sha512-dEquqYNJiGwY7iPfZ3wbXDI944iqanTSchrACLL2nOB+1r+h1Nzu2eH+DuPPvWvm5Ry7iAPeFlgEtP5bIp5U7Q== + dependencies: + array-back "^4.0.1" + deep-extend "~0.6.0" + typical "^5.2.0" + wordwrapjs "^4.0.0" + table@^5.0.0, table@^5.2.3: version "5.4.6" resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" @@ -11205,9 +11445,9 @@ table@^5.0.0, table@^5.2.3: string-width "^3.0.0" table@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/table/-/table-6.0.1.tgz#334fd5d74590251f6893f1296c29d533bbac1b32" - integrity sha512-fmr6168splcy/3XIvhSm5w6hYYOqyr3plAsd7OqoerzyoMnIpoxYuwrpdO2Cm22dh6KCnvirvigPrFZp+tdWFA== + version "6.0.3" + resolved "https://registry.yarnpkg.com/table/-/table-6.0.3.tgz#e5b8a834e37e27ad06de2e0fda42b55cfd8a0123" + integrity sha512-8321ZMcf1B9HvVX/btKv8mMZahCjn2aYrDlpqHaBFCfnox64edeH9kEid0vTLTRR8gWR2A20aDgeuTTea4sVtw== dependencies: ajv "^6.12.4" lodash "^4.17.20" @@ -11282,15 +11522,15 @@ ternary-stream@^3.0.0: through2 "^3.0.1" terser-webpack-plugin@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" - integrity sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA== + version "1.4.5" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" + integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== dependencies: cacache "^12.0.2" find-cache-dir "^2.1.0" is-wsl "^1.1.0" schema-utils "^1.0.0" - serialize-javascript "^2.1.2" + serialize-javascript "^4.0.0" source-map "^0.6.1" terser "^4.1.2" webpack-sources "^1.4.0" @@ -11363,10 +11603,11 @@ through2@2.X, through2@^2.0.0, through2@^2.0.3, through2@~2.0.0: xtend "~4.0.1" through2@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" - integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww== + version "3.0.2" + resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4" + integrity sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ== dependencies: + inherits "^2.0.4" readable-stream "2 || 3" through2@^4.0.2: @@ -11392,9 +11633,9 @@ timed-out@^4.0.0, timed-out@^4.0.1: integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= timers-browserify@^2.0.4: - version "2.0.11" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" - integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== + version "2.0.12" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" + integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== dependencies: setimmediate "^1.0.4" @@ -11514,9 +11755,9 @@ trim-repeated@^1.0.0: escape-string-regexp "^1.0.2" trim-trailing-lines@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz#7f0739881ff76657b7776e10874128004b625a94" - integrity sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA== + version "1.1.4" + resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0" + integrity sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ== trim@0.0.1: version "0.0.1" @@ -11545,15 +11786,10 @@ tsconfig-paths@^3.9.0: minimist "^1.2.0" strip-bom "^3.0.0" -tslib@^1.10.0: - version "1.11.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" - integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== - -tslib@^1.9.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" - integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== +tslib@^1.10.0, tslib@^1.9.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tty-browserify@0.0.0: version "0.0.0" @@ -11600,9 +11836,9 @@ type@^1.0.1: integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" - integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== + version "2.1.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.1.0.tgz#9bdc22c648cf8cf86dd23d32336a41cfb6475e3f" + integrity sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA== typedarray-to-buffer@^3.1.5: version "3.1.5" @@ -11616,10 +11852,23 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typical@^5.0.0, typical@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" + integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== + ua-parser-js@^0.7.18: - version "0.7.21" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777" - integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ== + version "0.7.22" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.22.tgz#960df60a5f911ea8f1c818f3747b99c6e177eae3" + integrity sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q== + +uglify-es@^3.3.9: + version "3.3.9" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" + integrity sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ== + dependencies: + commander "~2.13.0" + source-map "~0.6.1" uglify-js@3.4.x: version "3.4.10" @@ -11635,9 +11884,9 @@ ultron@~1.1.0: integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== unbzip2-stream@^1.0.9: - version "1.4.2" - resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.2.tgz#84eb9e783b186d8fb397515fbb656f312f1a7dbf" - integrity sha512-pZMVAofMrrHX6Ik39hCk470kulCbmZ2SWfQLPmTWqfJV/oUm0gn1CblvHdUu4+54Je6Jq34x8kY6XjTy6dMkOg== + version "1.4.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" + integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== dependencies: buffer "^5.2.1" through "^2.3.8" @@ -11653,15 +11902,16 @@ undertaker-registry@^1.0.0: integrity sha1-XkvaMI5KiirlhPm5pDWaSZglzFA= undertaker@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/undertaker/-/undertaker-1.2.1.tgz#701662ff8ce358715324dfd492a4f036055dfe4b" - integrity sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA== + version "1.3.0" + resolved "https://registry.yarnpkg.com/undertaker/-/undertaker-1.3.0.tgz#363a6e541f27954d5791d6fa3c1d321666f86d18" + integrity sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg== dependencies: arr-flatten "^1.0.1" arr-map "^2.0.0" bach "^1.0.0" collection-map "^1.0.0" es6-weak-map "^2.0.1" + fast-levenshtein "^1.0.0" last-run "^1.1.0" object.defaults "^1.0.0" object.reduce "^1.0.0" @@ -11713,9 +11963,9 @@ unified@^7.0.0: x-is-string "^0.1.0" unified@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/unified/-/unified-9.0.0.tgz#12b099f97ee8b36792dbad13d278ee2f696eed1d" - integrity sha512-ssFo33gljU3PdlWLjNp15Inqb77d6JnJSfyplGJPT/a+fNRNyCBeveBAYJdO5khKdF6WVHa/yYCC7Xl6BDwZUQ== + version "9.2.0" + resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.0.tgz#67a62c627c40589edebbf60f53edfd4d822027f8" + integrity sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg== dependencies: bail "^1.0.0" extend "^3.0.0" @@ -11782,9 +12032,9 @@ unist-util-find-all-after@^1.0.2: unist-util-is "^3.0.0" unist-util-find-all-after@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-3.0.1.tgz#95cc62f48812d879b4685a0512bf1b838da50e9a" - integrity sha512-0GICgc++sRJesLwEYDjFVJPJttBpVQaTNgc6Jw0Jhzvfs+jtKePEMu+uD+PqkRUrAvGQqwhpDwLGWo1PK8PDEw== + version "3.0.2" + resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-3.0.2.tgz#fdfecd14c5b7aea5e9ef38d5e0d5f774eeb561f6" + integrity sha512-xaTC/AGZ0rIM2gM28YVRAFPIZpzbpDtU3dRmp7EXlNVA8ziQc4hY3H7BHXM1J49nEmiqc3svnqMReW+PGqbZKQ== dependencies: unist-util-is "^4.0.0" @@ -11794,9 +12044,9 @@ unist-util-is@^3.0.0: integrity sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A== unist-util-is@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.0.2.tgz#c7d1341188aa9ce5b3cff538958de9895f14a5de" - integrity sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ== + version "4.0.3" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.0.3.tgz#e8b44db55fc20c43752b3346c116344d45d7c91d" + integrity sha512-bTofCFVx0iQM8Jqb1TBDVRIQW03YkD3p66JOd/aCWuqzlLyUtx1ZAGw/u+Zw+SttKvSVcvTiKYbfrtLoLefykw== unist-util-remove-position@^1.0.0: version "1.1.4" @@ -11832,9 +12082,9 @@ unist-util-visit-parents@^2.0.0: unist-util-is "^3.0.0" unist-util-visit-parents@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz#d4076af3011739c71d2ce99d05de37d545f4351d" - integrity sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g== + version "3.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" + integrity sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg== dependencies: "@types/unist" "^2.0.0" unist-util-is "^4.0.0" @@ -11847,9 +12097,9 @@ unist-util-visit@^1.1.0: unist-util-visit-parents "^2.0.0" unist-util-visit@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.2.tgz#3843782a517de3d2357b4c193b24af2d9366afb7" - integrity sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ== + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" + integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== dependencies: "@types/unist" "^2.0.0" unist-util-is "^4.0.0" @@ -11878,7 +12128,7 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -upath@^1.1.1: +upath@^1.1.0, upath@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== @@ -11889,9 +12139,9 @@ upper-case@^1.1.1: integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= 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== + version "4.4.0" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" + integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== dependencies: punycode "^2.1.0" @@ -11920,9 +12170,9 @@ url-to-options@^1.0.1: integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= url-toolkit@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/url-toolkit/-/url-toolkit-2.1.6.tgz#6d03246499e519aad224c44044a4ae20544154f2" - integrity sha512-UaZ2+50am4HwrV2crR/JAf63Q4VvPYphe63WGeoJxeu8gmOm0qxPt+KsukfakPNrX9aymGNEkkaoICwn+OuvBw== + version "2.2.1" + resolved "https://registry.yarnpkg.com/url-toolkit/-/url-toolkit-2.2.1.tgz#89009ed3d62a3574de079532a7266c14d2cc1c4f" + integrity sha512-8+DzgrtDZYZGhHaAop5WGVghMdCfOLGbhcArsJD0qDll71FXa7EeKxi2hilPIscn2nwMz4PRjML32Sz4JTN0Xw== url@^0.11.0: version "0.11.0" @@ -11974,7 +12224,7 @@ util@^0.11.0: dependencies: inherits "2.0.3" -utila@^0.4.0, utila@~0.4: +utila@~0.4: version "0.4.0" resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= @@ -11989,10 +12239,10 @@ uuid@^3.0.1, uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" - integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== +v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.1, v8-compile-cache@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" + integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== v8flags@^3.2.0: version "3.2.0" @@ -12034,14 +12284,14 @@ vfile-location@^2.0.0: integrity sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA== vfile-location@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-3.0.1.tgz#d78677c3546de0f7cd977544c367266764d31bb3" - integrity sha512-yYBO06eeN/Ki6Kh1QAkgzYpWT1d3Qln+ZCtSbJqFExPl1S3y2qqotJQXoh6qEvl/jDlgpUJolBn3PItVnnZRqQ== + version "3.2.0" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-3.2.0.tgz#d8e41fbcbd406063669ebf6c33d56ae8721d0f3c" + integrity sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA== -vfile-message@*: - version "2.0.3" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.3.tgz#0dd4f6879fb240a8099b22bd3755536c92e59ba5" - integrity sha512-qQg/2z8qnnBHL0psXyF72kCjb9YioIynvyltuNKFaUhRtqTIcIMP3xnBaPzirVZNuBrUe1qwFciSx2yApa4byw== +vfile-message@*, vfile-message@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" + integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ== dependencies: "@types/unist" "^2.0.0" unist-util-stringify-position "^2.0.0" @@ -12053,14 +12303,6 @@ vfile-message@^1.0.0: dependencies: unist-util-stringify-position "^1.1.1" -vfile-message@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" - integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ== - dependencies: - "@types/unist" "^2.0.0" - unist-util-stringify-position "^2.0.0" - vfile@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/vfile/-/vfile-3.0.1.tgz#47331d2abe3282424f4a4bb6acd20a44c4121803" @@ -12072,9 +12314,9 @@ vfile@^3.0.0: vfile-message "^1.0.0" vfile@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.1.0.tgz#d79248957f43225d57ff67a56effc67bef08946e" - integrity sha512-BaTPalregj++64xbGK6uIlsurN3BCRNM/P2Pg8HezlGzKd1O9PrwIac6bd9Pdx2uTb0QHoioZ+rXKolbVXEgJg== + version "4.2.0" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.0.tgz#26c78ac92eb70816b01d4565e003b7e65a2a0e01" + integrity sha512-a/alcwCvtuc8OX92rqqo7PflxiCgXRFjdyoGVuYV+qbgCb0GgZJRvIgCD4+U/Kl1yhaRsaTwksF88xbPyGsgpw== dependencies: "@types/unist" "^2.0.0" is-buffer "^2.0.0" @@ -12135,9 +12377,9 @@ vinyl@^0.5.0: replace-ext "0.0.1" vinyl@^2.0.0, vinyl@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" - integrity sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg== + version "2.2.1" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.1.tgz#23cfb8bbab5ece3803aa2c0a1eb28af7cbba1974" + integrity sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw== dependencies: clone "^2.1.1" clone-buffer "^1.0.0" @@ -12170,9 +12412,9 @@ watchpack@^1.7.4: watchpack-chokidar2 "^2.0.0" watchpack@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.0.0.tgz#b12248f32f0fd4799b7be0802ad1f6573a45955c" - integrity sha512-xSdCxxYZWNk3VK13bZRYhsQpfa8Vg63zXG+3pyU8ouqSLRCv4IGXIp9Kr226q6GBkGRlZrST2wwKtjfKz2m7Cg== + version "2.0.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.0.1.tgz#2f2192c542c82a3bcde76acd3411470c120426a8" + integrity sha512-vO8AKGX22ZRo6PiOFM9dC0re8IcKh8Kd/aH2zeqUc6w4/jBGlTy2P7fTC6ekT0NjVeGjgU2dGC5rNstKkeLEQg== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -12182,6 +12424,36 @@ webcomponents.js@^0.7.24: resolved "https://registry.yarnpkg.com/webcomponents.js/-/webcomponents.js-0.7.24.tgz#2116fbfa1468ec416a7befdaa333e1d118f69c04" integrity sha1-IRb7+hRo7EFqe+/aozPh0Rj2nAQ= +webpack-cli@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.2.0.tgz#10a09030ad2bd4d8b0f78322fba6ea43ec56aaaa" + integrity sha512-EIl3k88vaF4fSxWSgtAQR+VwicfLMTZ9amQtqS4o+TDPW9HGaEpbFBbAZ4A3ZOT5SOnMxNOzROsSTPiE8tBJPA== + dependencies: + "@webpack-cli/info" "^1.1.0" + "@webpack-cli/serve" "^1.1.0" + colorette "^1.2.1" + command-line-usage "^6.1.0" + commander "^6.2.0" + enquirer "^2.3.6" + execa "^4.1.0" + import-local "^3.0.2" + interpret "^2.2.0" + leven "^3.1.0" + rechoir "^0.7.0" + v8-compile-cache "^2.2.0" + webpack-merge "^4.2.2" + +webpack-concat-plugin@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/webpack-concat-plugin/-/webpack-concat-plugin-3.0.0.tgz#db34ae230794b634061bc2944053ed407619f138" + integrity sha512-DLdDbZXyrFR99wyAVC9P06HLjr2XujBmQdSbnQMK2o01H9U2NHsN5W76jeTVeXDq5OLvZf8r/se65ftRo3Prow== + dependencies: + concat-with-sourcemaps "^1.0.5" + globby "^8.0.1" + schema-utils "^0.4.5" + uglify-es "^3.3.9" + upath "^1.1.0" + webpack-log@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" @@ -12258,9 +12530,9 @@ webpack@^4.26.1: webpack-sources "^1.4.1" webpack@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.3.2.tgz#f88f6f2c54eaa1f68c8f37d8984657eaf68b00f0" - integrity sha512-DXsfHoI6lQAR3KnQh7+FsRfs9fs+TEvzXCA35UbKv4kVuzslg7QCMAcpFRZNDMjdtm9N/PoO54XEzGN9TeacQg== + version "5.4.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.4.0.tgz#4fdc6ec8a0ff9160701fb8f2eb8d06b33ecbae0f" + integrity sha512-udpYTyqz8toTTdaOsL2QKPLeZLt2IEm9qY7yTXuFEQhKu5bk0yQD9BtAdVQksmz4jFbbWOiWmm3NHarO0zr/ng== dependencies: "@types/eslint-scope" "^3.7.0" "@types/estree" "^0.0.45" @@ -12333,6 +12605,14 @@ word-wrap@^1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== +wordwrapjs@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.0.tgz#9aa9394155993476e831ba8e59fb5795ebde6800" + integrity sha512-Svqw723a3R34KvsMgpjFBYCgNOSdcW3mQFK4wIfhGQhtaFVOJmdYoXgi63ne3dTlWgatVcUc7t4HtQ/+bUVIzQ== + dependencies: + reduce-flatten "^2.0.0" + typical "^5.0.0" + worker-farm@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" @@ -12466,6 +12746,14 @@ yaml@^1.10.0: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== +yargs-parser@5.0.0-security.0: + version "5.0.0-security.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz#4ff7271d25f90ac15643b86076a2ab499ec9ee24" + integrity sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ== + dependencies: + camelcase "^3.0.0" + object.assign "^4.1.0" + yargs-parser@^10.0.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" @@ -12489,13 +12777,6 @@ yargs-parser@^18.1.2, yargs-parser@^18.1.3: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" - integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo= - dependencies: - camelcase "^3.0.0" - yargs@13.3.0: version "13.3.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" @@ -12545,10 +12826,10 @@ yargs@^15.4.1: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^7.0.0, yargs@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" - integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg= +yargs@^7.1.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.1.tgz#67f0ef52e228d4ee0d6311acede8850f53464df6" + integrity sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g== dependencies: camelcase "^3.0.0" cliui "^3.2.0" @@ -12562,7 +12843,7 @@ yargs@^7.0.0, yargs@^7.1.0: string-width "^1.0.2" which-module "^1.0.0" y18n "^3.2.1" - yargs-parser "^5.0.0" + yargs-parser "5.0.0-security.0" yauzl@^2.4.2: version "2.10.0" From 7d9208e951d07438fe63c4db5327a4bfca35aa19 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sun, 16 Aug 2020 20:24:45 +0200 Subject: [PATCH 039/202] WIP --- .eslintrc.js | 1 - package.json | 3 +- src/components/activitylog.js | 7 +- src/components/appRouter.js | 23 +- src/components/apphost.js | 7 +- src/components/backdrop/backdrop.js | 5 +- src/components/cardbuilder/cardBuilder.js | 5 +- .../cardbuilder/chaptercardbuilder.js | 4 +- src/components/channelMapper/channelMapper.js | 6 +- .../collectionEditor/collectionEditor.js | 8 +- src/components/dialogHelper/dialogHelper.js | 2 +- .../displaySettings/displaySettings.js | 11 +- src/components/favoriteitems.js | 2 +- src/components/filterdialog/filterdialog.js | 5 +- src/components/filtermenu/filtermenu.js | 4 +- src/components/groupedcards.js | 6 +- src/components/guide/guide.js | 9 +- .../homeScreenSettings/homeScreenSettings.js | 7 +- src/components/homesections/homesections.js | 17 +- src/components/htmlMediaHelper.js | 2 +- .../imageDownloader/imageDownloader.js | 6 +- src/components/imageUploader/imageUploader.js | 4 +- src/components/imageeditor/imageeditor.js | 16 +- src/components/images/imageLoader.js | 13 +- src/components/itemContextMenu.js | 10 +- src/components/itemHelper.js | 2 +- src/components/itemMediaInfo/itemMediaInfo.js | 4 +- .../itemidentifier/itemidentifier.js | 4 +- src/components/itemsrefresher.js | 4 +- src/components/layoutManager.js | 5 +- src/components/listview/listview.js | 6 +- src/components/maintabsmanager.js | 2 +- src/components/mediainfo/mediainfo.js | 2 +- .../metadataEditor/metadataEditor.js | 12 +- src/components/multiSelect/multiSelect.js | 6 +- src/components/notifications/notifications.js | 4 +- src/components/nowPlayingBar/nowPlayingBar.js | 19 +- src/components/packageManager.js | 2 +- src/components/playback/brightnessosd.js | 4 +- src/components/playback/mediasession.js | 15 +- src/components/playback/playbackmanager.js | 73 ++--- .../playback/playbackorientation.js | 4 +- .../playback/playerSelectionMenu.js | 8 +- src/components/playback/playersettingsmenu.js | 6 +- .../playback/remotecontrolautoplay.js | 4 +- src/components/playback/volumeosd.js | 4 +- .../playbackSettings/playbackSettings.js | 9 +- src/components/playerstats/playerstats.js | 9 +- .../playlisteditor/playlisteditor.js | 10 +- src/components/playmenu.js | 2 +- src/components/pluginManager.js | 50 ++- .../recordingcreator/recordingbutton.js | 4 +- .../recordingcreator/recordingcreator.js | 9 +- .../recordingcreator/recordingeditor.js | 8 +- .../recordingcreator/recordingfields.js | 9 +- .../recordingcreator/recordinghelper.js | 10 +- .../recordingcreator/seriesrecordingeditor.js | 8 +- src/components/refreshdialog/refreshdialog.js | 4 +- src/components/remotecontrol/remotecontrol.js | 19 +- src/components/search/searchfields.js | 2 +- src/components/search/searchresults.js | 6 +- src/components/shortcuts.js | 14 +- src/components/slideshow/slideshow.js | 6 +- .../subtitleeditor/subtitleeditor.js | 10 +- .../subtitlesettings/subtitlesettings.js | 9 +- src/components/subtitlesync/subtitlesync.js | 2 +- src/components/syncPlay/groupSelectionMenu.js | 9 +- src/components/syncPlay/syncPlayManager.js | 13 +- src/components/syncPlay/timeSyncManager.js | 5 +- src/components/themeMediaPlayer.js | 6 +- src/components/tunerPicker.js | 4 +- src/components/upnextdialog/upnextdialog.js | 5 +- .../userdatabuttons/userdatabuttons.js | 10 +- src/components/viewManager/viewManager.js | 3 +- src/controllers/dashboard/dashboard.js | 12 +- .../scheduledtasks/scheduledtasks.js | 2 +- src/controllers/favorites.js | 8 +- src/controllers/home.js | 6 +- src/controllers/hometab.js | 3 +- src/controllers/itemDetails/index.js | 32 +- src/controllers/list.js | 10 +- src/controllers/livetv/livetvchannels.js | 2 +- src/controllers/livetvguideprovider.js | 2 +- src/controllers/movies/moviegenres.js | 2 +- src/controllers/movies/movies.js | 2 +- src/controllers/movies/moviesrecommended.js | 4 +- src/controllers/movies/movietrailers.js | 2 +- src/controllers/music/musicalbums.js | 4 +- src/controllers/music/musicartists.js | 2 +- src/controllers/music/songs.js | 2 +- src/controllers/playback/video/index.js | 12 +- src/controllers/searchpage.js | 2 +- src/controllers/session/login/index.js | 6 +- src/controllers/session/selectServer/index.js | 10 +- src/controllers/shows/episodes.js | 2 +- src/controllers/shows/tvgenres.js | 2 +- src/controllers/shows/tvrecommended.js | 4 +- src/controllers/shows/tvshows.js | 2 +- src/controllers/user/menu/index.js | 2 +- src/controllers/user/profile/index.js | 2 +- src/elements/emby-button/emby-button.js | 109 ++++--- .../emby-itemrefreshindicator.js | 2 +- .../emby-itemscontainer.js | 7 +- .../emby-playstatebutton.js | 5 +- .../emby-ratingbutton/emby-ratingbutton.js | 5 +- src/elements/emby-tabs/emby-tabs.js | 305 +++++++++--------- src/libraries/navdrawer/navdrawer.js | 2 +- src/libraries/screensavermanager.js | 9 +- src/libraries/scroller.js | 1 + src/plugins/backdropScreensaver/plugin.js | 5 +- src/plugins/bookPlayer/plugin.js | 13 +- src/plugins/bookPlayer/tableOfContents.js | 2 +- src/plugins/chromecastPlayer/plugin.js | 26 +- src/plugins/experimentalWarnings/plugin.js | 8 +- src/plugins/htmlAudioPlayer/plugin.js | 14 +- src/plugins/htmlVideoPlayer/plugin.js | 44 +-- src/plugins/logoScreensaver/plugin.js | 4 +- src/plugins/photoPlayer/plugin.js | 9 +- src/plugins/playAccessValidation/plugin.js | 7 +- src/plugins/sessionPlayer/plugin.js | 10 +- src/plugins/youtubePlayer/plugin.js | 104 +++--- src/scripts/autoThemes.js | 5 +- src/scripts/browserDeviceProfile.js | 10 +- src/scripts/clientUtils.js | 2 +- src/scripts/deleteHelper.js | 6 +- src/scripts/gamepadtokey.js | 2 +- src/scripts/globalize.js | 26 +- src/scripts/inputManager.js | 6 +- src/scripts/itembynamedetailpage.js | 4 +- src/scripts/libraryMenu.js | 31 +- src/scripts/mouseManager.js | 3 +- src/scripts/routes.js | 132 ++++---- src/scripts/serverNotifications.js | 11 +- src/scripts/settings/userSettings.js | 2 +- src/scripts/settings/webSettings.js | 22 +- src/scripts/site.js | 68 ++-- src/scripts/standalone.js | 7 +- src/scripts/taskbutton.js | 12 +- src/scripts/themeManager.js | 8 + src/scripts/touchHelper.js | 2 +- webpack.common.js | 15 +- webpack.dev.js | 9 +- yarn.lock | 167 ++++++---- 143 files changed, 1000 insertions(+), 1008 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index e5ee2dfe86..d0c5cef897 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -25,7 +25,6 @@ module.exports = { 'eslint:recommended', // 'plugin:promise/recommended', 'plugin:import/errors', - 'plugin:import/warnings', 'plugin:eslint-comments/recommended', 'plugin:compat/recommended' ], diff --git a/package.json b/package.json index bfba7b363f..22b2a6ada7 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "browser-sync": "^2.26.13", "confusing-browser-globals": "^1.0.10", "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^5.1.1", + "copy-webpack-plugin": "^6.0.3", "css-loader": "^5.0.0", "cssnano": "^4.1.10", "del": "^6.0.0", @@ -80,7 +80,6 @@ "material-design-icons-iconfont": "^6.1.0", "native-promise-only": "^0.8.0-a", "page": "^1.11.6", - "query-string": "^6.13.6", "resize-observer-polyfill": "^1.5.1", "screenfull": "^5.0.2", "sortablejs": "^1.12.0", diff --git a/src/components/activitylog.js b/src/components/activitylog.js index df2ea5f611..c00856e3a1 100644 --- a/src/components/activitylog.js +++ b/src/components/activitylog.js @@ -1,10 +1,9 @@ -import events from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import globalize from '../scripts/globalize'; import dom from '../scripts/dom'; import * as datefns from 'date-fns'; import dfnshelper from '../scripts/dfnshelper'; import serverNotifications from '../scripts/serverNotifications'; -import connectionManager from 'jellyfin-apiclient'; import '../elements/emby-button/emby-button'; import './listview/listview.css'; @@ -141,7 +140,7 @@ class ActivityLog { const element = options.element; element.classList.add('activityLogListWidget'); element.addEventListener('click', onListClick.bind(this)); - const apiClient = window.connectionManager.getApiClient(options.serverId); + const apiClient = ConnectionManager.getApiClient(options.serverId); reloadData(this, element, apiClient); const onUpdate = onActivityLogUpdate.bind(this); this.updateFn = onUpdate; @@ -153,7 +152,7 @@ class ActivityLog { if (options) { options.element.classList.remove('activityLogListWidget'); - window.connectionManager.getApiClient(options.serverId).sendMessage('ActivityLogEntryStop', '0,1500'); + ConnectionManager.getApiClient(options.serverId).sendMessage('ActivityLogEntryStop', '0,1500'); } const onUpdate = this.updateFn; diff --git a/src/components/appRouter.js b/src/components/appRouter.js index b8df9d9f15..2ec42be3ac 100644 --- a/src/components/appRouter.js +++ b/src/components/appRouter.js @@ -1,9 +1,8 @@ -import appHost from './apphost'; +import { appHost } from './apphost'; import appSettings from '../scripts/settings/appSettings'; import backdrop from './backdrop/backdrop'; import browser from '../scripts/browser'; -import connectionManager from 'jellyfin-apiclient'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import globalize from '../scripts/globalize'; import itemHelper from './itemHelper'; import loading from './loading/loading'; @@ -95,7 +94,7 @@ class AppRouter { beginConnectionWizard() { backdrop.clearBackdrop(); loading.show(); - window.connectionManager.connect({ + window.ConnectionManager.connect({ enableAutoLogin: appSettings.enableAutoLogin() }).then((result) => { this.handleConnectionResult(result); @@ -154,7 +153,7 @@ class AppRouter { events.on(appHost, 'beforeexit', this.onBeforeExit); events.on(appHost, 'resume', this.onAppResume); - window.connectionManager.connect({ + window.ConnectionManager.connect({ enableAutoLogin: appSettings.enableAutoLogin() }).then((result) => { this.firstConnectionResult = result; @@ -210,7 +209,7 @@ class AppRouter { showItem(item, serverId, options) { // TODO: Refactor this so it only gets items, not strings. if (typeof (item) === 'string') { - const apiClient = serverId ? window.connectionManager.getApiClient(serverId) : window.connectionManager.currentApiClient(); + const apiClient = serverId ? window.ConnectionManager.getApiClient(serverId) : window.ConnectionManager.currentApiClient(); apiClient.getItem(apiClient.getCurrentUserId(), item).then((itemObject) => { this.showItem(itemObject, options); }); @@ -324,7 +323,7 @@ class AppRouter { url += '?' + ctx.querystring; } - import('' + url).then(({default: html}) => { + import(/* webpackChunkName: "[request]" */ `../controllers/${url}`).then((html) => { this.loadContent(ctx, route, html, request); }); } @@ -494,15 +493,15 @@ class AppRouter { } initApiClients() { - window.connectionManager.getApiClients().forEach((apiClient) => { + window.ConnectionManager.getApiClients().forEach((apiClient) => { this.initApiClient(apiClient, this); }); - events.on(window.connectionManager, 'apiclientcreated', this.onApiClientCreated); + events.on(window.ConnectionManager, 'apiclientcreated', this.onApiClientCreated); } onAppResume() { - const apiClient = window.connectionManager.currentApiClient(); + const apiClient = window.ConnectionManager.currentApiClient(); if (apiClient) { apiClient.ensureWebSocket(); @@ -520,7 +519,7 @@ class AppRouter { } } - const apiClient = window.connectionManager.currentApiClient(); + const apiClient = window.ConnectionManager.currentApiClient(); const pathname = ctx.pathname.toLowerCase(); console.debug('appRouter - processing path request ' + pathname); @@ -847,4 +846,4 @@ class AppRouter { } } -export default new AppRouter(); +export const appRouter = new AppRouter(); diff --git a/src/components/apphost.js b/src/components/apphost.js index c4b1396b15..281e070c75 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -1,6 +1,7 @@ + import appSettings from '../scripts/settings/appSettings'; import browser from '../scripts/browser'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import * as htmlMediaHelper from '../components/htmlMediaHelper'; import * as webSettings from '../scripts/settings/webSettings'; import globalize from '../scripts/globalize'; @@ -318,7 +319,7 @@ let deviceName; const appName = 'Jellyfin Web'; const appVersion = '10.7.0'; -const appHost = { +export const appHost = { getWindowState: function () { return document.windowState || 'Normal'; }, @@ -406,5 +407,3 @@ if (window.addEventListener) { window.addEventListener('focus', onAppVisible); window.addEventListener('blur', onAppHidden); } - -export default appHost; diff --git a/src/components/backdrop/backdrop.js b/src/components/backdrop/backdrop.js index acde031c20..98b5770094 100644 --- a/src/components/backdrop/backdrop.js +++ b/src/components/backdrop/backdrop.js @@ -1,6 +1,5 @@ import browser from '../../scripts/browser'; -import connectionManager from 'jellyfin-apiclient'; -import playbackManager from '../playback/playbackmanager'; +import { playbackManager } from '../playback/playbackmanager'; import dom from '../../scripts/dom'; import * as userSettings from '../../scripts/settings/userSettings'; import './backdrop.css'; @@ -177,7 +176,7 @@ import './backdrop.css'; function getItemImageUrls(item, imageOptions) { imageOptions = imageOptions || {}; - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = window.ConnectionManager.getApiClient(item.ServerId); if (item.BackdropImageTags && item.BackdropImageTags.length > 0) { return item.BackdropImageTags.map((imgTag, index) => { return apiClient.getScaledImageUrl(item.BackdropItemId || item.Id, Object.assign(imageOptions, { diff --git a/src/components/cardbuilder/cardBuilder.js b/src/components/cardbuilder/cardBuilder.js index 70c3c4f807..a000a06406 100644 --- a/src/components/cardbuilder/cardBuilder.js +++ b/src/components/cardbuilder/cardBuilder.js @@ -7,7 +7,6 @@ import datetime from '../../scripts/datetime'; import imageLoader from '../images/imageLoader'; -import connectionManager from 'jellyfin-apiclient'; import itemHelper from '../itemHelper'; import focusManager from '../focusManager'; import indicators from '../indicators/indicators'; @@ -15,7 +14,7 @@ import globalize from '../../scripts/globalize'; import layoutManager from '../layoutManager'; import dom from '../../scripts/dom'; import browser from '../../scripts/browser'; -import playbackManager from '../playback/playbackmanager'; +import { playbackManager } from '../playback/playbackmanager'; import itemShortcuts from '../shortcuts'; import imageHelper from '../../scripts/imagehelper'; import './card.css'; @@ -371,7 +370,7 @@ import '../guide/programs.css'; if (serverId !== lastServerId) { lastServerId = serverId; - apiClient = window.connectionManager.getApiClient(lastServerId); + apiClient = window.ConnectionManager.getApiClient(lastServerId); } if (options.indexBy) { diff --git a/src/components/cardbuilder/chaptercardbuilder.js b/src/components/cardbuilder/chaptercardbuilder.js index 2ebdcbe820..33e978c48d 100644 --- a/src/components/cardbuilder/chaptercardbuilder.js +++ b/src/components/cardbuilder/chaptercardbuilder.js @@ -7,7 +7,7 @@ import datetime from '../../scripts/datetime'; import imageLoader from '../images/imageLoader'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import layoutManager from '../layoutManager'; import browser from '../../scripts/browser'; @@ -48,7 +48,7 @@ import browser from '../../scripts/browser'; let html = ''; let itemsInRow = 0; - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); for (let i = 0, length = chapters.length; i < length; i++) { if (options.rows && itemsInRow === 0) { diff --git a/src/components/channelMapper/channelMapper.js b/src/components/channelMapper/channelMapper.js index b3a3dc41bc..f7c2dcc5c0 100644 --- a/src/components/channelMapper/channelMapper.js +++ b/src/components/channelMapper/channelMapper.js @@ -1,7 +1,7 @@ import dom from '../../scripts/dom'; import dialogHelper from '../dialogHelper/dialogHelper'; import loading from '../loading/loading'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import globalize from '../../scripts/globalize'; import actionsheet from '../actionSheet/actionSheet'; import '../../elements/emby-input/emby-input'; @@ -16,7 +16,7 @@ export default class channelMapper { function mapChannel(button, channelId, providerChannelId) { loading.show(); const providerId = options.providerId; - window.connectionManager.getApiClient(options.serverId).ajax({ + ConnectionManager.getApiClient(options.serverId).ajax({ type: 'POST', url: ApiClient.getUrl('LiveTv/ChannelMappings'), data: JSON.stringify({ @@ -59,7 +59,7 @@ export default class channelMapper { } function getChannelMappingOptions(serverId, providerId) { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); return apiClient.getJSON(apiClient.getUrl('LiveTv/ChannelMappingOptions', { providerId: providerId })); diff --git a/src/components/collectionEditor/collectionEditor.js b/src/components/collectionEditor/collectionEditor.js index e36abd7e0f..11de5af8fc 100644 --- a/src/components/collectionEditor/collectionEditor.js +++ b/src/components/collectionEditor/collectionEditor.js @@ -2,8 +2,8 @@ import dom from '../../scripts/dom'; import dialogHelper from '../dialogHelper/dialogHelper'; import loading from '../loading/loading'; import layoutManager from '../layoutManager'; -import connectionManager from 'jellyfin-apiclient'; -import appRouter from '../appRouter'; +import { ConnectionManager } from 'jellyfin-apiclient'; +import { appRouter } from '../appRouter'; import globalize from '../../scripts/globalize'; import '../../elements/emby-button/emby-button'; import '../../elements/emby-button/paper-icon-button-light'; @@ -25,7 +25,7 @@ import '../../assets/css/flexstyles.css'; const collectionId = panel.querySelector('#selectCollectionToAddTo').value; - const apiClient = window.connectionManager.getApiClient(currentServerId); + const apiClient = ConnectionManager.getApiClient(currentServerId); if (collectionId) { addToCollection(apiClient, panel, collectionId); @@ -106,7 +106,7 @@ import '../../assets/css/flexstyles.css'; EnableTotalRecordCount: false }; - const apiClient = window.connectionManager.getApiClient(currentServerId); + const apiClient = ConnectionManager.getApiClient(currentServerId); apiClient.getItems(apiClient.getCurrentUserId(), options).then(result => { let html = ''; diff --git a/src/components/dialogHelper/dialogHelper.js b/src/components/dialogHelper/dialogHelper.js index 4eee793a39..20c658df4e 100644 --- a/src/components/dialogHelper/dialogHelper.js +++ b/src/components/dialogHelper/dialogHelper.js @@ -1,4 +1,4 @@ -import appRouter from '../appRouter'; +import { appRouter } from '../appRouter'; import focusManager from '../focusManager'; import browser from '../../scripts/browser'; import layoutManager from '../layoutManager'; diff --git a/src/components/displaySettings/displaySettings.js b/src/components/displaySettings/displaySettings.js index d6e4bee2fe..575858648a 100644 --- a/src/components/displaySettings/displaySettings.js +++ b/src/components/displaySettings/displaySettings.js @@ -1,14 +1,13 @@ import browser from '../../scripts/browser'; import layoutManager from '../layoutManager'; -import pluginManager from '../pluginManager'; -import appHost from '../apphost'; +import { pluginManager } from '../pluginManager'; +import { appHost } from '../apphost'; import focusManager from '../focusManager'; import datetime from '../../scripts/datetime'; import globalize from '../../scripts/globalize'; import loading from '../loading/loading'; -import connectionManager from 'jellyfin-apiclient'; import skinManager from '../../scripts/themeManager'; -import events from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import '../../elements/emby-select/emby-select'; import '../../elements/emby-checkbox/emby-checkbox'; import '../../elements/emby-button/emby-button'; @@ -182,7 +181,7 @@ import '../../elements/emby-button/emby-button'; function onSubmit(e) { const self = this; - const apiClient = window.connectionManager.getApiClient(self.options.serverId); + const apiClient = ConnectionManager.getApiClient(self.options.serverId); const userId = self.options.userId; const userSettings = self.options.userSettings; @@ -221,7 +220,7 @@ import '../../elements/emby-button/emby-button'; loading.show(); const userId = self.options.userId; - const apiClient = window.connectionManager.getApiClient(self.options.serverId); + const apiClient = ConnectionManager.getApiClient(self.options.serverId); const userSettings = self.options.userSettings; return apiClient.getUser(userId).then(user => { diff --git a/src/components/favoriteitems.js b/src/components/favoriteitems.js index 7b56967fdd..cb1b61c43f 100644 --- a/src/components/favoriteitems.js +++ b/src/components/favoriteitems.js @@ -1,7 +1,7 @@ import loading from './loading/loading'; import cardBuilder from './cardbuilder/cardBuilder'; import dom from '../scripts/dom'; -import appHost from './apphost'; +import { appHost } from './apphost'; import imageLoader from './images/imageLoader'; import globalize from '../scripts/globalize'; import layoutManager from './layoutManager'; diff --git a/src/components/filterdialog/filterdialog.js b/src/components/filterdialog/filterdialog.js index 9c5ad5f71d..6c694c18f4 100644 --- a/src/components/filterdialog/filterdialog.js +++ b/src/components/filterdialog/filterdialog.js @@ -1,8 +1,7 @@ import dom from '../../scripts/dom'; import dialogHelper from '../dialogHelper/dialogHelper'; import globalize from '../../scripts/globalize'; -import connectionManager from 'jellyfin-apiclient'; -import events from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import '../../elements/emby-checkbox/emby-checkbox'; import '../../elements/emby-collapse/emby-collapse'; import './style.css'; @@ -420,7 +419,7 @@ import './style.css'; this.bindEvents(dlg); if (enableDynamicFilters(this.options.mode)) { dlg.classList.add('dynamicFilterDialog'); - const apiClient = window.connectionManager.getApiClient(this.options.serverId); + const apiClient = ConnectionManager.getApiClient(this.options.serverId); loadDynamicFilters(dlg, apiClient, apiClient.getCurrentUserId(), this.options.query); } }); diff --git a/src/components/filtermenu/filtermenu.js b/src/components/filtermenu/filtermenu.js index 46c3fc87b7..f098cc4574 100644 --- a/src/components/filtermenu/filtermenu.js +++ b/src/components/filtermenu/filtermenu.js @@ -3,7 +3,7 @@ import focusManager from '../focusManager'; import dialogHelper from '../dialogHelper/dialogHelper'; import inputManager from '../../scripts/inputManager'; import layoutManager from '../layoutManager'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import globalize from '../../scripts/globalize'; import * as userSettings from '../../scripts/settings/userSettings'; import '../../elements/emby-checkbox/emby-checkbox'; @@ -194,7 +194,7 @@ function initEditor(context, settings) { } } function loadDynamicFilters(context, options) { - const apiClient = window.connectionManager.getApiClient(options.serverId); + var apiClient = ConnectionManager.getApiClient(options.serverId); const filterMenuOptions = Object.assign(options.filterMenuOptions, { diff --git a/src/components/groupedcards.js b/src/components/groupedcards.js index c2714eba8d..3dd7f61402 100644 --- a/src/components/groupedcards.js +++ b/src/components/groupedcards.js @@ -1,13 +1,13 @@ /* eslint-disable indent */ import dom from '../scripts/dom'; -import appRouter from './appRouter'; -import connectionManager from 'jellyfin-apiclient'; +import { appRouter } from './appRouter'; +import { ConnectionManager } from 'jellyfin-apiclient'; function onGroupedCardClick(e, card) { const itemId = card.getAttribute('data-id'); const serverId = card.getAttribute('data-serverid'); - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = window.ConnectionManager.getApiClient(serverId); const userId = apiClient.getCurrentUserId(); const playedIndicator = card.querySelector('.playedIndicator'); const playedIndicatorHtml = playedIndicator ? playedIndicator.innerHTML : null; diff --git a/src/components/guide/guide.js b/src/components/guide/guide.js index 92a528f000..16d6813bdf 100644 --- a/src/components/guide/guide.js +++ b/src/components/guide/guide.js @@ -1,16 +1,15 @@ import inputManager from '../../scripts/inputManager'; import browser from '../../scripts/browser'; import globalize from '../../scripts/globalize'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import scrollHelper from '../../scripts/scrollHelper'; import serverNotifications from '../../scripts/serverNotifications'; import loading from '../loading/loading'; import datetime from '../../scripts/datetime'; import focusManager from '../focusManager'; -import playbackManager from '../playback/playbackmanager'; +import { playbackManager } from '../playback/playbackmanager'; import * as userSettings from '../../scripts/settings/userSettings'; import imageLoader from '../images/imageLoader'; -import events from 'jellyfin-apiclient'; import layoutManager from '../layoutManager'; import itemShortcuts from '../shortcuts'; import dom from '../../scripts/dom'; @@ -213,7 +212,7 @@ function Guide(options) { } function reloadGuide(context, newStartDate, scrollToTimeMs, focusToTimeMs, startTimeOfDayMs, focusProgramOnRender) { - const apiClient = window.connectionManager.getApiClient(options.serverId); + const apiClient = ConnectionManager.getApiClient(options.serverId); const channelQuery = { @@ -873,7 +872,7 @@ function Guide(options) { function reloadPage(page) { showLoading(); - const apiClient = window.connectionManager.getApiClient(options.serverId); + const apiClient = ConnectionManager.getApiClient(options.serverId); apiClient.getLiveTvGuideInfo().then(function (guideInfo) { setDateRange(page, guideInfo); diff --git a/src/components/homeScreenSettings/homeScreenSettings.js b/src/components/homeScreenSettings/homeScreenSettings.js index 361a91a9e3..6c62283327 100644 --- a/src/components/homeScreenSettings/homeScreenSettings.js +++ b/src/components/homeScreenSettings/homeScreenSettings.js @@ -3,10 +3,9 @@ import layoutManager from '../layoutManager'; import focusManager from '../focusManager'; import globalize from '../../scripts/globalize'; import loading from '../loading/loading'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import homeSections from '../homesections/homesections'; import dom from '../../scripts/dom'; -import events from 'jellyfin-apiclient'; import '../listview/listview.css'; import '../../elements/emby-select/emby-select'; import '../../elements/emby-checkbox/emby-checkbox'; @@ -385,7 +384,7 @@ import '../../elements/emby-checkbox/emby-checkbox'; function onSubmit(e) { const self = this; - const apiClient = window.connectionManager.getApiClient(self.options.serverId); + const apiClient = ConnectionManager.getApiClient(self.options.serverId); const userId = self.options.userId; const userSettings = self.options.userSettings; @@ -457,7 +456,7 @@ import '../../elements/emby-checkbox/emby-checkbox'; loading.show(); const userId = self.options.userId; - const apiClient = window.connectionManager.getApiClient(self.options.serverId); + const apiClient = ConnectionManager.getApiClient(self.options.serverId); const userSettings = self.options.userSettings; apiClient.getUser(userId).then(user => { diff --git a/src/components/homesections/homesections.js b/src/components/homesections/homesections.js index 60c5fc0ac4..27f1c4d79e 100644 --- a/src/components/homesections/homesections.js +++ b/src/components/homesections/homesections.js @@ -1,16 +1,15 @@ -import connectionManager from 'jellyfin-apiclient'; import cardBuilder from '../cardbuilder/cardBuilder'; import dom from '../../scripts/dom'; import layoutManager from '../layoutManager'; import imageLoader from '../images/imageLoader'; import globalize from '../../scripts/globalize'; -import appRouter from '../appRouter'; +import { appRouter } from '../appRouter'; import imageHelper from '../../scripts/imagehelper'; import '../../elements/emby-button/paper-icon-button-light'; import '../../elements/emby-itemscontainer/emby-itemscontainer'; import '../../elements/emby-scroller/emby-scroller'; import '../../elements/emby-button/emby-button'; -import './homesections'; +import './homesections.css'; /* eslint-disable indent */ @@ -212,7 +211,7 @@ import './homesections'; function getFetchLatestItemsFn(serverId, parentId, collectionType) { return function () { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = window.ConnectionManager.getApiClient(serverId); let limit = 16; if (enableScrollX()) { @@ -368,7 +367,7 @@ import './homesections'; function getContinueWatchingFetchFn(serverId) { return function () { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = window.ConnectionManager.getApiClient(serverId); const screenWidth = dom.getWindowSize().innerWidth; let limit; @@ -441,7 +440,7 @@ import './homesections'; function getContinueListeningFetchFn(serverId) { return function () { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = window.ConnectionManager.getApiClient(serverId); const screenWidth = dom.getWindowSize().innerWidth; let limit; @@ -514,7 +513,7 @@ import './homesections'; function getOnNowFetchFn(serverId) { return function () { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = window.ConnectionManager.getApiClient(serverId); return apiClient.getLiveTvRecommendedPrograms({ userId: apiClient.getCurrentUserId(), IsAiring: true, @@ -657,7 +656,7 @@ import './homesections'; function getNextUpFetchFn(serverId) { return function () { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = window.ConnectionManager.getApiClient(serverId); return apiClient.getNextUpEpisodes({ Limit: enableScrollX() ? 24 : 15, Fields: 'PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo,Path', @@ -728,7 +727,7 @@ import './homesections'; function getLatestRecordingsFetchFn(serverId, activeRecordingsOnly) { return function () { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = window.ConnectionManager.getApiClient(serverId); return apiClient.getLiveTvRecordings({ userId: apiClient.getCurrentUserId(), Limit: enableScrollX() ? 12 : 5, diff --git a/src/components/htmlMediaHelper.js b/src/components/htmlMediaHelper.js index 1fab10ef2b..45ab7f1e82 100644 --- a/src/components/htmlMediaHelper.js +++ b/src/components/htmlMediaHelper.js @@ -3,7 +3,7 @@ import appSettings from '../scripts/settings/appSettings' ; import browser from '../scripts/browser'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; export function getSavedVolume() { return appSettings.get('volume') || 1; diff --git a/src/components/imageDownloader/imageDownloader.js b/src/components/imageDownloader/imageDownloader.js index 5abdd588fa..66b6c1ff43 100644 --- a/src/components/imageDownloader/imageDownloader.js +++ b/src/components/imageDownloader/imageDownloader.js @@ -1,8 +1,8 @@ import dom from '../../scripts/dom'; import loading from '../loading/loading'; -import appHost from '../apphost'; +import { appHost } from '../apphost'; import dialogHelper from '../dialogHelper/dialogHelper'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import imageLoader from '../images/imageLoader'; import browser from '../../scripts/browser'; import layoutManager from '../layoutManager'; @@ -317,7 +317,7 @@ import '../cardbuilder/card.css'; loading.show(); import('./imageDownloader.template.html').then(({default: template}) => { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); currentItemId = itemId; currentItemType = itemType; diff --git a/src/components/imageUploader/imageUploader.js b/src/components/imageUploader/imageUploader.js index 2c32accca3..b6305fadb3 100644 --- a/src/components/imageUploader/imageUploader.js +++ b/src/components/imageUploader/imageUploader.js @@ -6,7 +6,7 @@ */ import dialogHelper from '../dialogHelper/dialogHelper'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import dom from '../../scripts/dom'; import loading from '../loading/loading'; import scrollHelper from '../../scripts/scrollHelper'; @@ -108,7 +108,7 @@ import './style.css'; return false; } - window.connectionManager.getApiClient(currentServerId).uploadItemImage(currentItemId, imageType, file).then(() => { + ConnectionManager.getApiClient(currentServerId).uploadItemImage(currentItemId, imageType, file).then(() => { dlg.querySelector('#uploadImage').value = ''; loading.hide(); diff --git a/src/components/imageeditor/imageeditor.js b/src/components/imageeditor/imageeditor.js index 09edc072fe..acb678c870 100644 --- a/src/components/imageeditor/imageeditor.js +++ b/src/components/imageeditor/imageeditor.js @@ -1,5 +1,5 @@ import dialogHelper from '../dialogHelper/dialogHelper'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import loading from '../loading/loading'; import dom from '../../scripts/dom'; import layoutManager from '../layoutManager'; @@ -8,7 +8,7 @@ import globalize from '../../scripts/globalize'; import scrollHelper from '../../scripts/scrollHelper'; import imageLoader from '../images/imageLoader'; import browser from '../../scripts/browser'; -import appHost from '../apphost'; +import { appHost } from '../apphost'; import '../cardbuilder/card.css'; import '../formdialog.css'; import '../../elements/emby-button/emby-button'; @@ -36,10 +36,10 @@ import './imageeditor.css'; let apiClient; if (item) { - apiClient = window.connectionManager.getApiClient(item.ServerId); + apiClient = ConnectionManager.getApiClient(item.ServerId); reloadItem(page, item, apiClient, focusContext); } else { - apiClient = window.connectionManager.getApiClient(currentItem.ServerId); + apiClient = ConnectionManager.getApiClient(currentItem.ServerId); apiClient.getItem(apiClient.getCurrentUserId(), currentItem.Id).then(function (item) { reloadItem(page, item, apiClient, focusContext); }); @@ -293,7 +293,7 @@ import './imageeditor.css'; function showActionSheet(context, imageCard) { const itemId = imageCard.getAttribute('data-id'); const serverId = imageCard.getAttribute('data-serverid'); - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); const type = imageCard.getAttribute('data-imagetype'); const index = parseInt(imageCard.getAttribute('data-index')); @@ -404,7 +404,7 @@ import './imageeditor.css'; const type = this.getAttribute('data-imagetype'); let index = this.getAttribute('data-index'); index = index === 'null' ? null : parseInt(index); - const apiClient = window.connectionManager.getApiClient(currentItem.ServerId); + const apiClient = ConnectionManager.getApiClient(currentItem.ServerId); deleteImage(context, currentItem.Id, type, index, apiClient, true); }); @@ -412,7 +412,7 @@ import './imageeditor.css'; const type = this.getAttribute('data-imagetype'); const index = this.getAttribute('data-index'); const newIndex = this.getAttribute('data-newindex'); - const apiClient = window.connectionManager.getApiClient(currentItem.ServerId); + const apiClient = ConnectionManager.getApiClient(currentItem.ServerId); moveImage(context, apiClient, currentItem.Id, type, index, newIndex, dom.parentWithClass(this, 'itemsContainer')); }); } @@ -424,7 +424,7 @@ import './imageeditor.css'; loading.show(); import('./imageeditor.template.html').then(({default: template}) => { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) { const dialogOptions = { removeOnClose: true diff --git a/src/components/images/imageLoader.js b/src/components/images/imageLoader.js index f4a141bc90..47ea382056 100644 --- a/src/components/images/imageLoader.js +++ b/src/components/images/imageLoader.js @@ -1,6 +1,6 @@ import * as lazyLoader from '../lazyLoader/lazyLoaderIntersectionObserver'; import * as userSettings from '../../scripts/settings/userSettings'; -import * as blurhash from 'blurhash'; +import { decode, isBlurhashValid } from 'blurhash'; import './style.css'; /* eslint-disable indent */ @@ -13,7 +13,7 @@ import './style.css'; } function itemBlurhashing(target, blurhashstr) { - if (blurhash.isBlurhashValid(blurhashstr)) { + if (isBlurhashValid(blurhashstr)) { // Although the default values recommended by Blurhash developers is 32x32, a size of 18x18 seems to be the sweet spot for us, // improving the performance and reducing the memory usage, while retaining almost full blur quality. // Lower values had more visible pixelation @@ -21,7 +21,7 @@ import './style.css'; const height = 18; let pixels; try { - pixels = blurhash.decode(blurhashstr, width, height); + pixels = decode(blurhashstr, width, height); } catch (err) { console.error('Blurhash decode error: ', err); target.classList.add('non-blurhashable'); @@ -124,15 +124,18 @@ import './style.css'; export function lazyChildren(elem) { if (userSettings.enableBlurhash()) { - for (const lazyElem of elem.querySelectorAll('.lazy')) { + const lazyElems = Array.from(elem.querySelectorAll('.lazy')); + console.warn(lazyElems); + lazyElems.forEach((lazyElem) => { const blurhashstr = lazyElem.getAttribute('data-blurhash'); if (!lazyElem.classList.contains('blurhashed', 'non-blurhashable') && blurhashstr) { itemBlurhashing(lazyElem, blurhashstr); } else if (!blurhashstr && !lazyElem.classList.contains('blurhashed')) { lazyElem.classList.add('non-blurhashable'); } - } + }); } + console.warn(elem); lazyLoader.lazyChildren(elem, fillImage); } diff --git a/src/components/itemContextMenu.js b/src/components/itemContextMenu.js index ff58a901f4..e16063f648 100644 --- a/src/components/itemContextMenu.js +++ b/src/components/itemContextMenu.js @@ -1,11 +1,11 @@ -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import browser from '../scripts/browser'; import globalize from '../scripts/globalize'; import actionsheet from './actionSheet/actionSheet'; -import appHost from './apphost'; -import appRouter from './appRouter'; +import { appHost } from './apphost'; +import { appRouter } from './appRouter'; import itemHelper from './itemHelper'; -import playbackManager from './playback/playbackmanager'; +import { playbackManager } from './playback/playbackmanager'; /* eslint-disable indent */ export function getCommands(options) { @@ -330,7 +330,7 @@ import playbackManager from './playback/playbackmanager'; function executeCommand(item, id, options) { const itemId = item.Id; const serverId = item.ServerId; - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); return new Promise(function (resolve, reject) { switch (id) { diff --git a/src/components/itemHelper.js b/src/components/itemHelper.js index b6f30d7abd..de771546b0 100644 --- a/src/components/itemHelper.js +++ b/src/components/itemHelper.js @@ -1,4 +1,4 @@ -import appHost from './apphost'; +import { appHost } from './apphost'; import globalize from '../scripts/globalize'; export function getDisplayName(item, options = {}) { diff --git a/src/components/itemMediaInfo/itemMediaInfo.js b/src/components/itemMediaInfo/itemMediaInfo.js index 9e036fba9a..1d254c2645 100644 --- a/src/components/itemMediaInfo/itemMediaInfo.js +++ b/src/components/itemMediaInfo/itemMediaInfo.js @@ -8,7 +8,7 @@ import dialogHelper from '../dialogHelper/dialogHelper'; import layoutManager from '../layoutManager'; import globalize from '../../scripts/globalize'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import loading from '../loading/loading'; import '../../elements/emby-select/emby-select'; import '../listview/listview.css'; @@ -163,7 +163,7 @@ import '../../assets/css/flexstyles.css'; } function loadMediaInfo(itemId, serverId, template) { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); return apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(item => { const dialogOptions = { size: 'small', diff --git a/src/components/itemidentifier/itemidentifier.js b/src/components/itemidentifier/itemidentifier.js index 77b04a1a51..b65a986dea 100644 --- a/src/components/itemidentifier/itemidentifier.js +++ b/src/components/itemidentifier/itemidentifier.js @@ -7,7 +7,7 @@ import dialogHelper from '../dialogHelper/dialogHelper'; import loading from '../loading/loading'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import globalize from '../../scripts/globalize'; import scrollHelper from '../../scripts/scrollHelper'; import layoutManager from '../layoutManager'; @@ -31,7 +31,7 @@ import '../cardbuilder/card.css'; let currentSearchResult; function getApiClient() { - return window.connectionManager.getApiClient(currentServerId); + return ConnectionManager.getApiClient(currentServerId); } function searchForIdentificationResults(page) { diff --git a/src/components/itemsrefresher.js b/src/components/itemsrefresher.js index d283619990..9960cac331 100644 --- a/src/components/itemsrefresher.js +++ b/src/components/itemsrefresher.js @@ -1,6 +1,6 @@ -import playbackManager from './playback/playbackmanager'; +import { playbackManager } from './playback/playbackmanager'; import serverNotifications from '../scripts/serverNotifications'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; function onUserDataChanged(e, apiClient, userData) { const instance = this; diff --git a/src/components/layoutManager.js b/src/components/layoutManager.js index c5555d0eb5..eaa1dc50bc 100644 --- a/src/components/layoutManager.js +++ b/src/components/layoutManager.js @@ -1,7 +1,8 @@ -import appHost from './apphost'; + +import { appHost } from './apphost'; import browser from '../scripts/browser'; import { set, get } from '../scripts/settings/appSettings'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; function setLayout(instance, layout, selectedLayout) { if (layout === selectedLayout) { diff --git a/src/components/listview/listview.js b/src/components/listview/listview.js index 33bbdc756c..a94e3a1438 100644 --- a/src/components/listview/listview.js +++ b/src/components/listview/listview.js @@ -8,7 +8,7 @@ import itemHelper from '../itemHelper'; import mediaInfo from '../mediainfo/mediainfo'; import indicators from '../indicators/indicators'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import layoutManager from '../layoutManager'; import globalize from '../../scripts/globalize'; import datetime from '../../scripts/datetime'; @@ -77,7 +77,7 @@ import '../../elements/emby-playstatebutton/emby-playstatebutton'; } function getImageUrl(item, width) { - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); let itemId; const options = { @@ -106,7 +106,7 @@ import '../../elements/emby-playstatebutton/emby-playstatebutton'; } function getChannelImageUrl(item, width) { - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); const options = { maxWidth: width, type: 'Primary' diff --git a/src/components/maintabsmanager.js b/src/components/maintabsmanager.js index 07a1502823..2884794bcc 100644 --- a/src/components/maintabsmanager.js +++ b/src/components/maintabsmanager.js @@ -1,6 +1,6 @@ import dom from '../scripts/dom'; import browser from '../scripts/browser'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import '../elements/emby-tabs/emby-tabs'; import '../elements/emby-button/emby-button'; diff --git a/src/components/mediainfo/mediainfo.js b/src/components/mediainfo/mediainfo.js index 270cfae6d6..73193f3758 100644 --- a/src/components/mediainfo/mediainfo.js +++ b/src/components/mediainfo/mediainfo.js @@ -1,6 +1,6 @@ import datetime from '../../scripts/datetime'; import globalize from '../../scripts/globalize'; -import appRouter from '../appRouter'; +import { appRouter } from '../appRouter'; import itemHelper from '../itemHelper'; import indicators from '../indicators/indicators'; import 'material-design-icons-iconfont'; diff --git a/src/components/metadataEditor/metadataEditor.js b/src/components/metadataEditor/metadataEditor.js index 32a0a3751f..b6c33f4af1 100644 --- a/src/components/metadataEditor/metadataEditor.js +++ b/src/components/metadataEditor/metadataEditor.js @@ -4,7 +4,7 @@ import dialogHelper from '../dialogHelper/dialogHelper'; import datetime from '../../scripts/datetime'; import loading from '../loading/loading'; import focusManager from '../focusManager'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import globalize from '../../scripts/globalize'; import shell from '../../scripts/shell'; import '../../elements/emby-checkbox/emby-checkbox'; @@ -290,7 +290,7 @@ import '../../assets/css/flexstyles.css'; } function getApiClient() { - return window.connectionManager.getApiClient(currentItem.ServerId); + return ConnectionManager.getApiClient(currentItem.ServerId); } function bindAll(elems, eventName, fn) { @@ -370,7 +370,7 @@ import '../../assets/css/flexstyles.css'; } function getItem(itemId, serverId) { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); if (itemId) { return apiClient.getItem(apiClient.getCurrentUserId(), itemId); @@ -380,7 +380,7 @@ import '../../assets/css/flexstyles.css'; } function getEditorConfig(itemId, serverId) { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); if (itemId) { return apiClient.getJSON(apiClient.getUrl('Items/' + itemId + '/MetadataEditor')); @@ -1068,7 +1068,7 @@ import '../../assets/css/flexstyles.css'; currentContext = dlg; - init(dlg, window.connectionManager.getApiClient(serverId)); + init(dlg, ConnectionManager.getApiClient(serverId)); reload(dlg, itemId, serverId); }); @@ -1095,7 +1095,7 @@ import '../../assets/css/flexstyles.css'; currentContext = elem; - init(elem, window.connectionManager.getApiClient(serverId)); + init(elem, ConnectionManager.getApiClient(serverId)); reload(elem, itemId, serverId); focusManager.autoFocus(elem); diff --git a/src/components/multiSelect/multiSelect.js b/src/components/multiSelect/multiSelect.js index 52182d4403..e37deb2d36 100644 --- a/src/components/multiSelect/multiSelect.js +++ b/src/components/multiSelect/multiSelect.js @@ -1,7 +1,7 @@ import browser from '../../scripts/browser'; -import appHost from '../apphost'; +import { appHost } from '../apphost'; import loading from '../loading/loading'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import globalize from '../../scripts/globalize'; import dom from '../../scripts/dom'; import './multiSelect.css'; @@ -170,7 +170,7 @@ import './multiSelect.css'; } function showMenuForSelectedItems(e) { - const apiClient = window.connectionManager.currentApiClient(); + const apiClient = ConnectionManager.currentApiClient(); apiClient.getCurrentUser().then(user => { const menuItems = []; diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js index 1eca2c3807..c50fbc68e1 100644 --- a/src/components/notifications/notifications.js +++ b/src/components/notifications/notifications.js @@ -1,6 +1,6 @@ import serverNotifications from '../../scripts/serverNotifications'; -import playbackManager from '../playback/playbackmanager'; -import events from 'jellyfin-apiclient'; +import { playbackManager } from '../playback/playbackmanager'; +import { events } from 'jellyfin-apiclient'; import globalize from '../../scripts/globalize'; function onOneDocumentClick() { diff --git a/src/components/nowPlayingBar/nowPlayingBar.js b/src/components/nowPlayingBar/nowPlayingBar.js index 9607fadcb1..4a794c9568 100644 --- a/src/components/nowPlayingBar/nowPlayingBar.js +++ b/src/components/nowPlayingBar/nowPlayingBar.js @@ -1,13 +1,12 @@ import datetime from '../../scripts/datetime'; -import events from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import browser from '../../scripts/browser'; import imageLoader from '../../scripts/imagehelper'; import layoutManager from '../layoutManager'; -import playbackManager from '../playback/playbackmanager'; +import { playbackManager } from '../playback/playbackmanager'; import nowPlayingHelper from '../playback/nowplayinghelper'; -import appHost from '../apphost'; +import { appHost } from '../apphost'; import dom from '../../scripts/dom'; -import connectionManager from 'jellyfin-apiclient'; import itemContextMenu from '../itemContextMenu'; import '../../elements/emby-button/paper-icon-button-light'; import '../../elements/emby-ratingbutton/emby-ratingbutton'; @@ -452,7 +451,7 @@ import '../../elements/emby-ratingbutton/emby-ratingbutton'; if (item.SeriesPrimaryImageTag) { options.tag = item.SeriesPrimaryImageTag; - return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); + return ConnectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); } } @@ -460,12 +459,12 @@ import '../../elements/emby-ratingbutton/emby-ratingbutton'; if (item.SeriesThumbImageTag) { options.tag = item.SeriesThumbImageTag; - return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); + return ConnectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); } if (item.ParentThumbImageTag) { options.tag = item.ParentThumbImageTag; - return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.ParentThumbItemId, options); + return ConnectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.ParentThumbItemId, options); } } @@ -482,12 +481,12 @@ import '../../elements/emby-ratingbutton/emby-ratingbutton'; if (item.ImageTags && item.ImageTags[options.type]) { options.tag = item.ImageTags[options.type]; - return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.PrimaryImageItemId || item.Id, options); + return ConnectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.PrimaryImageItemId || item.Id, options); } if (item.AlbumId && item.AlbumPrimaryImageTag) { options.tag = item.AlbumPrimaryImageTag; - return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.AlbumId, options); + return ConnectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.AlbumId, options); } return null; @@ -548,7 +547,7 @@ import '../../elements/emby-ratingbutton/emby-ratingbutton'; if (nowPlayingItem.Id) { if (isRefreshing) { - const apiClient = window.connectionManager.getApiClient(nowPlayingItem.ServerId); + const apiClient = ConnectionManager.getApiClient(nowPlayingItem.ServerId); apiClient.getItem(apiClient.getCurrentUserId(), nowPlayingItem.Id).then(function (item) { const userData = item.UserData || {}; const likes = userData.Likes == null ? '' : userData.Likes; diff --git a/src/components/packageManager.js b/src/components/packageManager.js index 0fd5bb7502..3890577b24 100644 --- a/src/components/packageManager.js +++ b/src/components/packageManager.js @@ -1,5 +1,5 @@ import appSettings from '../scripts/settings/appSettings'; -import pluginManager from './pluginManager'; +import { pluginManager } from './pluginManager'; /* eslint-disable indent */ class PackageManager { diff --git a/src/components/playback/brightnessosd.js b/src/components/playback/brightnessosd.js index 935656e230..044cb6b754 100644 --- a/src/components/playback/brightnessosd.js +++ b/src/components/playback/brightnessosd.js @@ -1,5 +1,5 @@ -import events from 'jellyfin-apiclient'; -import playbackManager from './playbackmanager'; +import { events } from 'jellyfin-apiclient'; +import { playbackManager } from './playbackmanager'; import dom from '../../scripts/dom'; import browser from '../../scripts/browser'; import './iconosd.css'; diff --git a/src/components/playback/mediasession.js b/src/components/playback/mediasession.js index 52ef5c36ed..6283b978fe 100644 --- a/src/components/playback/mediasession.js +++ b/src/components/playback/mediasession.js @@ -1,7 +1,6 @@ -import playbackManager from '../playback/playbackmanager'; +import { playbackManager } from '../playback/playbackmanager'; import nowPlayingHelper from '../playback/nowplayinghelper'; -import events from 'jellyfin-apiclient'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; /* eslint-disable indent */ // Reports media playback to the device for lock screen control @@ -16,16 +15,16 @@ import connectionManager from 'jellyfin-apiclient'; } else if (options.type === 'Primary' && item.SeriesPrimaryImageTag) { options.tag = item.SeriesPrimaryImageTag; - return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); + return ConnectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); } else if (options.type === 'Thumb') { if (item.SeriesThumbImageTag) { options.tag = item.SeriesThumbImageTag; - return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); + return ConnectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); } else if (item.ParentThumbImageTag) { options.tag = item.ParentThumbImageTag; - return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.ParentThumbItemId, options); + return ConnectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.ParentThumbItemId, options); } } @@ -38,11 +37,11 @@ import connectionManager from 'jellyfin-apiclient'; if (item.ImageTags && item.ImageTags[options.type]) { options.tag = item.ImageTags[options.type]; - return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.Id, options); + return ConnectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.Id, options); } else if (item.AlbumId && item.AlbumPrimaryImageTag) { options.tag = item.AlbumPrimaryImageTag; - return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.AlbumId, options); + return ConnectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.AlbumId, options); } return null; diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index af60dd61dd..f602a8e495 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -1,15 +1,14 @@ -import events from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import datetime from '../../scripts/datetime'; import appSettings from '../../scripts/settings/appSettings'; import itemHelper from '../itemHelper'; -import pluginManager from '../pluginManager'; +import { pluginManager } from '../pluginManager'; import PlayQueueManager from './playqueuemanager'; import * as userSettings from '../../scripts/settings/userSettings'; import globalize from '../../scripts/globalize'; -import connectionManager from 'jellyfin-apiclient'; import loading from '../loading/loading'; -import appHost from '../apphost'; -import screenfull from 'screenfull'; +import { appHost } from '../apphost'; +import * as Screenfull from 'screenfull'; function enableLocalPlaylistManagement(player) { if (player.getPlaylist) { @@ -24,8 +23,8 @@ function enableLocalPlaylistManagement(player) { } function bindToFullscreenChange(player) { - if (screenfull.isEnabled) { - screenfull.on('change', function () { + if (Screenfull.isEnabled) { + Screenfull.on('change', function () { events.trigger(player, 'fullscreenchange'); }); } else { @@ -69,7 +68,7 @@ function reportPlayback(playbackManagerInstance, state, player, reportPlaylist, addPlaylistToPlaybackReport(playbackManagerInstance, info, player, serverId); } - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); const reportPlaybackPromise = apiClient[method](info); // Notify that report has been sent reportPlaybackPromise.then(() => { @@ -106,7 +105,7 @@ function normalizeName(t) { } function getItemsForPlayback(serverId, query) { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); if (query.Ids && query.Ids.split(',').length === 1) { const itemId = query.Ids.split(','); @@ -870,7 +869,7 @@ class PlaybackManager { const promises = players.filter(displayPlayerIndividually).map(getPlayerTargets); return Promise.all(promises).then(function (responses) { - return window.connectionManager.currentApiClient().getCurrentUser().then(function (user) { + return ConnectionManager.currentApiClient().getCurrentUser().then(function (user) { const targets = []; targets.push({ @@ -1368,7 +1367,7 @@ class PlaybackManager { function getSavedMaxStreamingBitrate(apiClient, mediaType) { if (!apiClient) { // This should hopefully never happen - apiClient = window.connectionManager.currentApiClient(); + apiClient = ConnectionManager.currentApiClient(); } const endpointInfo = apiClient.getSavedEndpointInfo() || {}; @@ -1391,7 +1390,7 @@ class PlaybackManager { const mediaType = playerData.streamInfo ? playerData.streamInfo.mediaType : null; const currentItem = self.currentItem(player); - const apiClient = currentItem ? window.connectionManager.getApiClient(currentItem.ServerId) : window.connectionManager.currentApiClient(); + const apiClient = currentItem ? ConnectionManager.getApiClient(currentItem.ServerId) : ConnectionManager.currentApiClient(); return getSavedMaxStreamingBitrate(apiClient, mediaType); }; @@ -1405,7 +1404,7 @@ class PlaybackManager { const mediaType = playerData.streamInfo ? playerData.streamInfo.mediaType : null; const currentItem = self.currentItem(player); - const apiClient = currentItem ? window.connectionManager.getApiClient(currentItem.ServerId) : window.connectionManager.currentApiClient(); + const apiClient = currentItem ? ConnectionManager.getApiClient(currentItem.ServerId) : ConnectionManager.currentApiClient(); const endpointInfo = apiClient.getSavedEndpointInfo() || {}; return appSettings.enableAutomaticBitrateDetection(endpointInfo.IsInNetwork, mediaType); @@ -1417,7 +1416,7 @@ class PlaybackManager { return player.setMaxStreamingBitrate(options); } - const apiClient = window.connectionManager.getApiClient(self.currentItem(player).ServerId); + const apiClient = ConnectionManager.getApiClient(self.currentItem(player).ServerId); apiClient.getEndpointInfo().then(function (endpointInfo) { const playerData = getPlayerData(player); @@ -1448,12 +1447,12 @@ class PlaybackManager { return player.isFullscreen(); } - if (!screenfull.isEnabled) { + if (!Screenfull.isEnabled) { // iOS Safari return document.webkitIsFullScreen; } - return screenfull.isFullscreen; + return Screenfull.isFullscreen; }; self.toggleFullscreen = function (player) { @@ -1462,8 +1461,8 @@ class PlaybackManager { return player.toggleFullscreen(); } - if (screenfull.isEnabled) { - screenfull.toggle(); + if (Screenfull.isEnabled) { + Screenfull.toggle(); } else { // iOS Safari if (document.webkitIsFullScreen && document.webkitCancelFullscreen) { @@ -1679,7 +1678,7 @@ class PlaybackManager { const subtitleStreamIndex = params.SubtitleStreamIndex == null ? getPlayerData(player).subtitleStreamIndex : params.SubtitleStreamIndex; let currentMediaSource = self.currentMediaSource(player); - const apiClient = window.connectionManager.getApiClient(currentItem.ServerId); + const apiClient = ConnectionManager.getApiClient(currentItem.ServerId); if (ticks) { ticks = parseInt(ticks); @@ -1835,7 +1834,7 @@ class PlaybackManager { }, queryOptions)); } else if (firstItem.Type === 'Episode' && items.length === 1 && getPlayer(firstItem, options).supportsProgress !== false) { promise = new Promise(function (resolve, reject) { - const apiClient = window.connectionManager.getApiClient(firstItem.ServerId); + const apiClient = ConnectionManager.getApiClient(firstItem.ServerId); apiClient.getCurrentUser().then(function (user) { if (!user.Configuration.EnableNextEpisodeAutoPlay || !firstItem.SeriesId) { @@ -2066,7 +2065,7 @@ class PlaybackManager { return playOther(items, options, user); } - const apiClient = window.connectionManager.getApiClient(firstItem.ServerId); + const apiClient = ConnectionManager.getApiClient(firstItem.ServerId); return getIntros(firstItem, apiClient, options).then(function (introsResult) { const introItems = introsResult.Items; @@ -2129,14 +2128,14 @@ class PlaybackManager { const mediaType = item.MediaType; const onBitrateDetectionFailure = function () { - return playAfterBitrateDetect(getSavedMaxStreamingBitrate(window.connectionManager.getApiClient(item.ServerId), mediaType), item, playOptions, onPlaybackStartedFn); + return playAfterBitrateDetect(getSavedMaxStreamingBitrate(ConnectionManager.getApiClient(item.ServerId), mediaType), item, playOptions, onPlaybackStartedFn); }; if (!isServerItem(item) || itemHelper.isLocalItem(item)) { return onBitrateDetectionFailure(); } - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); apiClient.getEndpointInfo().then(function (endpointInfo) { if ((mediaType === 'Video' || mediaType === 'Audio') && appSettings.enableAutomaticBitrateDetection(endpointInfo.IsInNetwork, mediaType)) { return apiClient.detectBitrate().then(function (bitrate) { @@ -2255,7 +2254,7 @@ class PlaybackManager { return Promise.all([promise, player.getDeviceProfile(item)]).then(function (responses) { const deviceProfile = responses[1]; - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); const mediaSourceId = playOptions.mediaSourceId; const audioStreamIndex = playOptions.audioStreamIndex; @@ -2300,11 +2299,11 @@ class PlaybackManager { const startPosition = options.startPositionTicks || 0; const mediaType = options.mediaType || item.MediaType; const player = getPlayer(item, options); - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); // Call this just to ensure the value is recorded, it is needed with getSavedMaxStreamingBitrate return apiClient.getEndpointInfo().then(function () { - const maxBitrate = getSavedMaxStreamingBitrate(window.connectionManager.getApiClient(item.ServerId), mediaType); + const maxBitrate = getSavedMaxStreamingBitrate(ConnectionManager.getApiClient(item.ServerId), mediaType); return player.getDeviceProfile(item).then(function (deviceProfile) { return getPlaybackMediaSource(player, apiClient, deviceProfile, maxBitrate, item, startPosition, options.mediaSourceId, options.audioStreamIndex, options.subtitleStreamIndex).then(function (mediaSource) { @@ -2320,11 +2319,11 @@ class PlaybackManager { const mediaType = options.mediaType || item.MediaType; // TODO: Remove the true forceLocalPlayer hack const player = getPlayer(item, options, true); - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); // Call this just to ensure the value is recorded, it is needed with getSavedMaxStreamingBitrate return apiClient.getEndpointInfo().then(function () { - const maxBitrate = getSavedMaxStreamingBitrate(window.connectionManager.getApiClient(item.ServerId), mediaType); + const maxBitrate = getSavedMaxStreamingBitrate(ConnectionManager.getApiClient(item.ServerId), mediaType); return player.getDeviceProfile(item).then(function (deviceProfile) { return getPlaybackInfo(player, apiClient, item, deviceProfile, maxBitrate, startPosition, false, null, null, null, null).then(function (playbackInfoResult) { @@ -2708,7 +2707,7 @@ class PlaybackManager { const queueDirectToPlayer = player && !enableLocalPlaylistManagement(player); if (queueDirectToPlayer) { - const apiClient = window.connectionManager.getApiClient(items[0].ServerId); + const apiClient = ConnectionManager.getApiClient(items[0].ServerId); player.getDeviceProfile(items[0]).then(function (profile) { setStreamUrls(items, profile, self.getMaxStreamingBitrate(player), apiClient, 0).then(function () { @@ -3158,13 +3157,13 @@ class PlaybackManager { streamInfo.lastMediaInfoQuery = new Date().getTime(); - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); if (!apiClient.isMinServerVersion('3.2.70.7')) { return; } - window.connectionManager.getApiClient(serverId).getLiveStreamMediaInfo(liveStreamId).then(function (info) { + ConnectionManager.getApiClient(serverId).getLiveStreamMediaInfo(liveStreamId).then(function (info) { mediaSource.MediaStreams = info.MediaStreams; events.trigger(player, 'mediastreamschange'); }, function () { @@ -3221,7 +3220,7 @@ class PlaybackManager { return Promise.reject(); } - const apiClient = window.connectionManager.getApiClient(nextItem.item.ServerId); + const apiClient = ConnectionManager.getApiClient(nextItem.item.ServerId); return apiClient.getItem(apiClient.getCurrentUserId(), nextItem.item.Id); } @@ -3362,7 +3361,7 @@ class PlaybackManager { return player.playTrailers(item); } - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); const instance = this; @@ -3394,7 +3393,7 @@ class PlaybackManager { } getSubtitleUrl(textStream, serverId) { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); return !textStream.IsExternalUrl ? apiClient.getUrl(textStream.DeliveryUrl) : textStream.DeliveryUrl; } @@ -3474,7 +3473,7 @@ class PlaybackManager { return player.instantMix(item); } - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); const options = {}; options.UserId = apiClient.getCurrentUserId(); @@ -3758,7 +3757,7 @@ class PlaybackManager { } } -const playbackManager = new PlayQueueManager(); +export const playbackManager = new PlaybackManager(); window.addEventListener('beforeunload', function () { try { @@ -3767,5 +3766,3 @@ window.addEventListener('beforeunload', function () { console.error('error in onAppClose: ' + err); } }); - -export default playbackManager; diff --git a/src/components/playback/playbackorientation.js b/src/components/playback/playbackorientation.js index 6c44d5bbca..79776abd0c 100644 --- a/src/components/playback/playbackorientation.js +++ b/src/components/playback/playbackorientation.js @@ -1,7 +1,7 @@ -import playbackManager from './playbackmanager'; +import { playbackManager } from './playbackmanager'; import layoutManager from '../layoutManager'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; let orientationLocked; diff --git a/src/components/playback/playerSelectionMenu.js b/src/components/playback/playerSelectionMenu.js index 1bd9090254..acc6e24819 100644 --- a/src/components/playback/playerSelectionMenu.js +++ b/src/components/playback/playerSelectionMenu.js @@ -1,11 +1,11 @@ import appSettings from '../../scripts/settings/appSettings'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import browser from '../../scripts/browser'; import loading from '../loading/loading'; -import playbackManager from '../playback/playbackmanager'; -import appRouter from '../appRouter'; +import { playbackManager } from '../playback/playbackmanager'; +import { appRouter } from '../appRouter'; import globalize from '../../scripts/globalize'; -import appHost from '../apphost'; +import { appHost } from '../apphost'; import { enable, isEnabled, supported } from '../../scripts/autocast'; function mirrorItem(info, player) { diff --git a/src/components/playback/playersettingsmenu.js b/src/components/playback/playersettingsmenu.js index acec830912..5107489498 100644 --- a/src/components/playback/playersettingsmenu.js +++ b/src/components/playback/playersettingsmenu.js @@ -1,6 +1,6 @@ -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import actionsheet from '../actionSheet/actionSheet'; -import playbackManager from '../playback/playbackmanager'; +import { playbackManager } from '../playback/playbackmanager'; import globalize from '../../scripts/globalize'; import qualityoptions from '../qualityOptions'; @@ -251,7 +251,7 @@ export function show(options) { return showWithUser(options, player, null); } - const apiClient = window.connectionManager.getApiClient(currentItem.ServerId); + var apiClient = ConnectionManager.getApiClient(currentItem.ServerId); return apiClient.getCurrentUser().then(function (user) { return showWithUser(options, player, user); }); diff --git a/src/components/playback/remotecontrolautoplay.js b/src/components/playback/remotecontrolautoplay.js index 532a71237d..8e8e8797fd 100644 --- a/src/components/playback/remotecontrolautoplay.js +++ b/src/components/playback/remotecontrolautoplay.js @@ -1,5 +1,5 @@ -import events from 'jellyfin-apiclient'; -import playbackManager from '../playback/playbackmanager'; +import { events } from 'jellyfin-apiclient'; +import { playbackManager } from '../playback/playbackmanager'; function transferPlayback(oldPlayer, newPlayer) { const state = playbackManager.getPlayerState(oldPlayer); diff --git a/src/components/playback/volumeosd.js b/src/components/playback/volumeosd.js index 9e84017838..7096c246a7 100644 --- a/src/components/playback/volumeosd.js +++ b/src/components/playback/volumeosd.js @@ -1,6 +1,6 @@ -import events from 'jellyfin-apiclient'; -import playbackManager from './playbackmanager'; +import { events } from 'jellyfin-apiclient'; +import { playbackManager } from './playbackmanager'; import dom from '../../scripts/dom'; import browser from '../../scripts/browser'; import './iconosd.css'; diff --git a/src/components/playbackSettings/playbackSettings.js b/src/components/playbackSettings/playbackSettings.js index 4d123bb738..aefa69dbc6 100644 --- a/src/components/playbackSettings/playbackSettings.js +++ b/src/components/playbackSettings/playbackSettings.js @@ -1,12 +1,11 @@ import browser from '../../scripts/browser'; import appSettings from '../../scripts/settings/appSettings'; -import appHost from '../apphost'; +import { appHost } from '../apphost'; import focusManager from '../focusManager'; import qualityoptions from '../qualityOptions'; import globalize from '../../scripts/globalize'; import loading from '../loading/loading'; -import connectionManager from 'jellyfin-apiclient'; -import events from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import '../../elements/emby-select/emby-select'; import '../../elements/emby-checkbox/emby-checkbox'; @@ -258,7 +257,7 @@ import '../../elements/emby-checkbox/emby-checkbox'; function onSubmit(e) { const self = this; - const apiClient = window.connectionManager.getApiClient(self.options.serverId); + const apiClient = ConnectionManager.getApiClient(self.options.serverId); const userId = self.options.userId; const userSettings = self.options.userSettings; @@ -305,7 +304,7 @@ import '../../elements/emby-checkbox/emby-checkbox'; loading.show(); const userId = self.options.userId; - const apiClient = window.connectionManager.getApiClient(self.options.serverId); + const apiClient = ConnectionManager.getApiClient(self.options.serverId); const userSettings = self.options.userSettings; apiClient.getUser(userId).then(user => { diff --git a/src/components/playerstats/playerstats.js b/src/components/playerstats/playerstats.js index 59f885f320..66d87aad92 100644 --- a/src/components/playerstats/playerstats.js +++ b/src/components/playerstats/playerstats.js @@ -1,9 +1,8 @@ -import connectionManager from 'jellyfin-apiclient'; -import events from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import '../../elements/emby-button/paper-icon-button-light'; import globalize from '../../scripts/globalize'; import layoutManager from '../layoutManager'; -import playbackManager from '../playback/playbackmanager'; +import { playbackManager } from '../playback/playbackmanager'; import playMethodHelper from '../playback/playmethodhelper'; import syncPlayManager from '../syncPlay/syncPlayManager'; import './playerstats.css'; @@ -95,7 +94,7 @@ import './playerstats.css'; return Promise.resolve(instance.lastSession); } - const apiClient = window.connectionManager.getApiClient(playbackManager.currentItem(player).ServerId); + const apiClient = ConnectionManager.getApiClient(playbackManager.currentItem(player).ServerId); return apiClient.getSessions({ deviceId: apiClient.deviceId() @@ -414,7 +413,7 @@ import './playerstats.css'; name: 'Original Media Info' }); - const apiClient = window.connectionManager.getApiClient(playbackManager.currentItem(player).ServerId); + var apiClient = ConnectionManager.getApiClient(playbackManager.currentItem(player).ServerId); if (syncPlayManager.isSyncPlayEnabled() && apiClient.isMinServerVersion('10.6.0')) { categories.push({ stats: getSyncPlayStats(), diff --git a/src/components/playlisteditor/playlisteditor.js b/src/components/playlisteditor/playlisteditor.js index a3221ff3c6..340fe5a993 100644 --- a/src/components/playlisteditor/playlisteditor.js +++ b/src/components/playlisteditor/playlisteditor.js @@ -2,10 +2,10 @@ import dom from '../../scripts/dom'; import dialogHelper from '../dialogHelper/dialogHelper'; import loading from '../loading/loading'; import layoutManager from '../layoutManager'; -import playbackManager from '../playback/playbackmanager'; -import connectionManager from 'jellyfin-apiclient'; +import { playbackManager } from '../playback/playbackmanager'; +import { ConnectionManager } from 'jellyfin-apiclient'; import * as userSettings from '../../scripts/settings/userSettings'; -import appRouter from '../appRouter'; +import { appRouter } from '../appRouter'; import globalize from '../../scripts/globalize'; import '../../elements/emby-button/emby-button'; import '../../elements/emby-input/emby-input'; @@ -22,7 +22,7 @@ import '../formdialog.css'; const panel = dom.parentWithClass(this, 'dialog'); const playlistId = panel.querySelector('#selectPlaylistToAddTo').value; - const apiClient = window.connectionManager.getApiClient(currentServerId); + const apiClient = ConnectionManager.getApiClient(currentServerId); if (playlistId) { userSettings.set('playlisteditor-lastplaylistid', playlistId); @@ -113,7 +113,7 @@ import '../formdialog.css'; EnableTotalRecordCount: false }; - const apiClient = window.connectionManager.getApiClient(currentServerId); + const apiClient = ConnectionManager.getApiClient(currentServerId); apiClient.getItems(apiClient.getCurrentUserId(), options).then(result => { let html = ''; diff --git a/src/components/playmenu.js b/src/components/playmenu.js index 8831b4d7b7..412c5375e0 100644 --- a/src/components/playmenu.js +++ b/src/components/playmenu.js @@ -1,6 +1,6 @@ import actionsheet from './actionSheet/actionSheet'; import datetime from '../scripts/datetime'; -import playbackManager from './playback/playbackmanager'; +import { playbackManager } from './playback/playbackmanager'; import globalize from '../scripts/globalize'; export function show(options) { diff --git a/src/components/pluginManager.js b/src/components/pluginManager.js index 116281c482..e794a2c984 100644 --- a/src/components/pluginManager.js +++ b/src/components/pluginManager.js @@ -1,4 +1,4 @@ -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import globalize from '../scripts/globalize'; /* eslint-disable indent */ @@ -41,7 +41,7 @@ import globalize from '../scripts/globalize'; return Promise.resolve(plugin); } else { return new Promise((resolve, reject) => { - this.#loadStrings(plugin) + PluginManager.loadStrings(plugin) .then(function () { resolve(plugin); }) @@ -52,39 +52,35 @@ import globalize from '../scripts/globalize'; loadPlugin(pluginSpec) { if (typeof pluginSpec === 'string') { - console.debug('Loading plugin (via deprecated requirejs method): ' + pluginSpec); + console.debug('Loading plugin (via dynamic import): ' + pluginSpec); - return new Promise((resolve, reject) => { - require([pluginSpec], (pluginFactory) => { - const plugin = pluginFactory.default ? new pluginFactory.default() : new pluginFactory(); + import(/* webpackChunkName: "[request]" */ `../plugins/${pluginSpec}`).then((plugin) => { + // See if it's already installed + const existing = this.plugins.filter(function (p) { + return p.id === plugin.id; + })[0]; - // See if it's already installed - const existing = this.pluginsList.filter(function (p) { - return p.id === plugin.id; - })[0]; + if (existing) { + return Promise.resolve(pluginSpec); + } - if (existing) { - resolve(pluginSpec); - } + plugin.installUrl = pluginSpec; - plugin.installUrl = pluginSpec; + const separatorIndex = Math.max(pluginSpec.lastIndexOf('/'), pluginSpec.lastIndexOf('\\')); + plugin.baseUrl = pluginSpec.substring(0, separatorIndex); - const separatorIndex = Math.max(pluginSpec.lastIndexOf('/'), pluginSpec.lastIndexOf('\\')); - plugin.baseUrl = pluginSpec.substring(0, separatorIndex); + const paths = {}; + paths[plugin.id] = plugin.baseUrl; - const paths = {}; - paths[plugin.id] = plugin.baseUrl; - - requirejs.config({ - waitSeconds: 0, - paths: paths - }); - - this.#registerPlugin(plugin).then(resolve).catch(reject); + requirejs.config({ + waitSeconds: 0, + paths: paths }); + + this.#registerPlugin(plugin).then(Promise.resolve).catch(Promise.reject); }); } else if (pluginSpec.then) { - return pluginSpec.then(pluginBuilder => { + return pluginSpec.then(({ default: pluginBuilder }) => { return pluginBuilder(); }).then((plugin) => { console.debug(`Plugin loaded: ${plugin.id}`); @@ -148,4 +144,4 @@ import globalize from '../scripts/globalize'; /* eslint-enable indent */ -export default new PluginManager(); +export const pluginManager = new PluginManager(); diff --git a/src/components/recordingcreator/recordingbutton.js b/src/components/recordingcreator/recordingbutton.js index a898cf4a5b..41195961d4 100644 --- a/src/components/recordingcreator/recordingbutton.js +++ b/src/components/recordingcreator/recordingbutton.js @@ -1,4 +1,4 @@ -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import dom from '../../scripts/dom'; import recordingHelper from './recordinghelper'; import '../../elements/emby-button/paper-icon-button-light'; @@ -53,7 +53,7 @@ class RecordingButton { } refresh(serverId, itemId) { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); const self = this; apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) { self.refreshItem(item); diff --git a/src/components/recordingcreator/recordingcreator.js b/src/components/recordingcreator/recordingcreator.js index fe5b506c96..06d17de75d 100644 --- a/src/components/recordingcreator/recordingcreator.js +++ b/src/components/recordingcreator/recordingcreator.js @@ -2,13 +2,12 @@ import dialogHelper from '../dialogHelper/dialogHelper'; import globalize from '../../scripts/globalize'; import layoutManager from '../layoutManager'; import mediaInfo from '../mediainfo/mediainfo'; -import connectionManager from 'jellyfin-apiclient'; import loading from '../loading/loading'; import scrollHelper from '../../scripts/scrollHelper'; import datetime from '../../scripts/datetime'; import imageLoader from '../images/imageLoader'; import recordingFields from './recordingfields'; -import events from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import '../../elements/emby-button/emby-button'; import '../../elements/emby-button/paper-icon-button-light'; import '../../elements/emby-checkbox/emby-checkbox'; @@ -102,7 +101,7 @@ function renderRecording(context, defaultTimer, program, apiClient, refreshRecor function reload(context, programId, serverId, refreshRecordingStateOnly) { loading.show(); - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); const promise1 = apiClient.getNewLiveTvTimerDefaults({ programId: programId }); const promise2 = apiClient.getLiveTvProgram(programId, apiClient.getCurrentUserId()); @@ -117,8 +116,8 @@ function reload(context, programId, serverId, refreshRecordingStateOnly) { function executeCloseAction(action, programId, serverId) { if (action === 'play') { - import('../playback/playbackmanager').then(({ default: playbackManager }) => { - const apiClient = connectionManager.getApiClient(serverId); + import('../playback/playbackmanager').then((playbackManager) => { + const apiClient = ConnectionManager.getApiClient(serverId); apiClient.getLiveTvProgram(programId, apiClient.getCurrentUserId()).then(function (item) { playbackManager.play({ diff --git a/src/components/recordingcreator/recordingeditor.js b/src/components/recordingcreator/recordingeditor.js index 6c5a380d11..068fc60a43 100644 --- a/src/components/recordingcreator/recordingeditor.js +++ b/src/components/recordingcreator/recordingeditor.js @@ -2,7 +2,7 @@ import dialogHelper from '../dialogHelper/dialogHelper'; import globalize from '../../scripts/globalize'; import layoutManager from '../layoutManager'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import loading from '../loading/loading'; import scrollHelper from '../../scripts/scrollHelper'; import '../../assets/css/scrollstyles.css'; @@ -42,7 +42,7 @@ function closeDialog(isDeleted) { function onSubmit(e) { const form = this; - const apiClient = window.connectionManager.getApiClient(currentServerId); + const apiClient = ConnectionManager.getApiClient(currentServerId); apiClient.getLiveTvTimer(currentItemId).then(function (item) { item.PrePaddingSeconds = form.querySelector('#txtPrePaddingMinutes').value * 60; @@ -62,7 +62,7 @@ function init(context) { }); context.querySelector('.btnCancelRecording').addEventListener('click', function () { - const apiClient = window.connectionManager.getApiClient(currentServerId); + const apiClient = ConnectionManager.getApiClient(currentServerId); deleteTimer(apiClient, currentItemId).then(function () { closeDialog(true); @@ -76,7 +76,7 @@ function reload(context, id) { loading.show(); currentItemId = id; - const apiClient = window.connectionManager.getApiClient(currentServerId); + const apiClient = ConnectionManager.getApiClient(currentServerId); apiClient.getLiveTvTimer(id).then(function (result) { renderTimer(context, result, apiClient); loading.hide(); diff --git a/src/components/recordingcreator/recordingfields.js b/src/components/recordingcreator/recordingfields.js index 39e549ee86..ad14ff273c 100644 --- a/src/components/recordingcreator/recordingfields.js +++ b/src/components/recordingcreator/recordingfields.js @@ -1,10 +1,9 @@ import globalize from '../../scripts/globalize'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import serverNotifications from '../../scripts/serverNotifications'; import loading from '../loading/loading'; import dom from '../../scripts/dom'; import recordingHelper from './recordinghelper'; -import events from 'jellyfin-apiclient'; import '../../elements/emby-button/emby-button'; import '../../elements/emby-button/paper-icon-button-light'; import './recordingfields.css'; @@ -46,7 +45,7 @@ function loadData(parent, program, apiClient) { function fetchData(instance) { const options = instance.options; - const apiClient = window.connectionManager.getApiClient(options.serverId); + const apiClient = ConnectionManager.getApiClient(options.serverId); options.parent.querySelector('.recordingFields').classList.remove('hide'); return apiClient.getLiveTvProgram(options.programId, apiClient.getCurrentUserId()).then(function (program) { @@ -197,7 +196,7 @@ function onRecordChange(e) { const self = this; const options = this.options; - const apiClient = window.connectionManager.getApiClient(options.serverId); + const apiClient = ConnectionManager.getApiClient(options.serverId); const button = dom.parentWithTag(e.target, 'BUTTON'); const isChecked = !button.querySelector('.material-icons').classList.contains('recordingIcon-active'); @@ -236,7 +235,7 @@ function onRecordSeriesChange(e) { const self = this; const options = this.options; - const apiClient = window.connectionManager.getApiClient(options.serverId); + const apiClient = ConnectionManager.getApiClient(options.serverId); const button = dom.parentWithTag(e.target, 'BUTTON'); const isChecked = !button.querySelector('.material-icons').classList.contains('recordingIcon-active'); diff --git a/src/components/recordingcreator/recordinghelper.js b/src/components/recordingcreator/recordinghelper.js index 8ba1c4dfef..9ff64f6819 100644 --- a/src/components/recordingcreator/recordinghelper.js +++ b/src/components/recordingcreator/recordinghelper.js @@ -1,6 +1,6 @@ import globalize from '../../scripts/globalize'; import loading from '../loading/loading'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; /*eslint prefer-const: "error"*/ @@ -40,7 +40,7 @@ function cancelTimerWithConfirmation(timerId, serverId) { }).then(function () { loading.show(); - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); cancelTimer(apiClient, timerId, true).then(resolve, reject); }, reject); }); @@ -60,7 +60,7 @@ function cancelSeriesTimerWithConfirmation(timerId, serverId) { }).then(function () { loading.show(); - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); apiClient.cancelLiveTvSeriesTimer(timerId).then(function () { import('../toast/toast').then((toast) => { toast(globalize.translate('SeriesCancelled')); @@ -141,7 +141,7 @@ function showMultiCancellationPrompt(serverId, programId, timerId, timerStatus, buttons: items }).then(function (result) { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); if (result === 'canceltimer') { loading.show(); @@ -167,7 +167,7 @@ function showMultiCancellationPrompt(serverId, programId, timerId, timerStatus, } function toggleRecording(serverId, programId, timerId, timerStatus, seriesTimerId) { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); const hasTimer = timerId && timerStatus !== 'Cancelled'; if (seriesTimerId && hasTimer) { // cancel diff --git a/src/components/recordingcreator/seriesrecordingeditor.js b/src/components/recordingcreator/seriesrecordingeditor.js index 6b887280e6..282794bb33 100644 --- a/src/components/recordingcreator/seriesrecordingeditor.js +++ b/src/components/recordingcreator/seriesrecordingeditor.js @@ -1,7 +1,7 @@ import dialogHelper from '../dialogHelper/dialogHelper'; import globalize from '../../scripts/globalize'; import layoutManager from '../layoutManager'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import loading from '../loading/loading'; import scrollHelper from '../../scripts/scrollHelper'; import datetime from '../../scripts/datetime'; @@ -64,7 +64,7 @@ function closeDialog(isDeleted) { function onSubmit(e) { const form = this; - const apiClient = window.connectionManager.getApiClient(currentServerId); + const apiClient = ConnectionManager.getApiClient(currentServerId); apiClient.getLiveTvSeriesTimer(currentItemId).then(function (item) { item.PrePaddingSeconds = form.querySelector('#txtPrePaddingMinutes').value * 60; @@ -92,7 +92,7 @@ function init(context) { }); context.querySelector('.btnCancelRecording').addEventListener('click', function () { - const apiClient = window.connectionManager.getApiClient(currentServerId); + const apiClient = ConnectionManager.getApiClient(currentServerId); deleteTimer(apiClient, currentItemId).then(function () { closeDialog(true); }); @@ -102,7 +102,7 @@ function init(context) { } function reload(context, id) { - const apiClient = window.connectionManager.getApiClient(currentServerId); + const apiClient = ConnectionManager.getApiClient(currentServerId); loading.show(); if (typeof id === 'string') { diff --git a/src/components/refreshdialog/refreshdialog.js b/src/components/refreshdialog/refreshdialog.js index 1338e4b722..b6ea07f466 100644 --- a/src/components/refreshdialog/refreshdialog.js +++ b/src/components/refreshdialog/refreshdialog.js @@ -2,7 +2,7 @@ import dom from '../../scripts/dom'; import dialogHelper from '../dialogHelper/dialogHelper'; import loading from '../loading/loading'; import layoutManager from '../layoutManager'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import globalize from '../../scripts/globalize'; import '../../elements/emby-input/emby-input'; import '../../elements/emby-button/emby-button'; @@ -66,7 +66,7 @@ function onSubmit(e) { const dlg = dom.parentWithClass(e.target, 'dialog'); const options = instance.options; - const apiClient = window.connectionManager.getApiClient(options.serverId); + const apiClient = ConnectionManager.getApiClient(options.serverId); const replaceAllMetadata = dlg.querySelector('#selectMetadataRefreshMode').value === 'all'; diff --git a/src/components/remotecontrol/remotecontrol.js b/src/components/remotecontrol/remotecontrol.js index eb897d1fec..d3410274ed 100644 --- a/src/components/remotecontrol/remotecontrol.js +++ b/src/components/remotecontrol/remotecontrol.js @@ -2,11 +2,10 @@ import datetime from '../../scripts/datetime'; import backdrop from '../backdrop/backdrop'; import listView from '../listview/listview'; import imageLoader from '../images/imageLoader'; -import playbackManager from '../playback/playbackmanager'; +import { playbackManager } from '../playback/playbackmanager'; import nowPlayingHelper from '../playback/nowplayinghelper'; -import events from 'jellyfin-apiclient'; -import connectionManager from 'jellyfin-apiclient'; -import appHost from '../apphost'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; +import { appHost } from '../apphost'; import globalize from '../../scripts/globalize'; import layoutManager from '../layoutManager'; import * as userSettings from '../../scripts/settings/userSettings'; @@ -96,18 +95,18 @@ function seriesImageUrl(item, options) { options.type = options.type || 'Primary'; if (options.type === 'Primary' && item.SeriesPrimaryImageTag) { options.tag = item.SeriesPrimaryImageTag; - return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); + return ConnectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); } if (options.type === 'Thumb') { if (item.SeriesThumbImageTag) { options.tag = item.SeriesThumbImageTag; - return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); + return ConnectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); } if (item.ParentThumbImageTag) { options.tag = item.ParentThumbImageTag; - return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.ParentThumbItemId, options); + return ConnectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.ParentThumbItemId, options); } } @@ -120,12 +119,12 @@ function imageUrl(item, options) { if (item.ImageTags && item.ImageTags[options.type]) { options.tag = item.ImageTags[options.type]; - return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.PrimaryImageItemId || item.Id, options); + return ConnectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.PrimaryImageItemId || item.Id, options); } if (item.AlbumId && item.AlbumPrimaryImageTag) { options.tag = item.AlbumPrimaryImageTag; - return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.AlbumId, options); + return ConnectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.AlbumId, options); } return null; @@ -216,7 +215,7 @@ function updateNowPlayingInfo(context, state, serverId) { openAlbum: false, positionTo: contextButton }; - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); apiClient.getItem(apiClient.getCurrentUserId(), item.Id).then(function (fullItem) { apiClient.getCurrentUser().then(function (user) { contextButton.addEventListener('click', function () { diff --git a/src/components/search/searchfields.js b/src/components/search/searchfields.js index 3b985c05a9..01cd504fd1 100644 --- a/src/components/search/searchfields.js +++ b/src/components/search/searchfields.js @@ -1,6 +1,6 @@ import layoutManager from '../layoutManager'; import globalize from '../../scripts/globalize'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import browser from '../../scripts/browser'; import AlphaPicker from '../alphaPicker/alphaPicker'; import '../../elements/emby-input/emby-input'; diff --git a/src/components/search/searchresults.js b/src/components/search/searchresults.js index 9fe1e7b60d..a73c489d92 100644 --- a/src/components/search/searchresults.js +++ b/src/components/search/searchresults.js @@ -1,8 +1,8 @@ import layoutManager from '../layoutManager'; import globalize from '../../scripts/globalize'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import cardBuilder from '../cardbuilder/cardBuilder'; -import appRouter from '../appRouter'; +import { appRouter } from '../appRouter'; import '../../elements/emby-scroller/emby-scroller'; import '../../elements/emby-itemscontainer/emby-itemscontainer'; import '../../elements/emby-button/emby-button'; @@ -606,7 +606,7 @@ class SearchResults { embed(options.element, this, options); } search(value) { - const apiClient = window.connectionManager.getApiClient(this.options.serverId); + const apiClient = ConnectionManager.getApiClient(this.options.serverId); search(this, apiClient, this.options.element, value); } diff --git a/src/components/shortcuts.js b/src/components/shortcuts.js index 2f83a342f2..3472d7a72e 100644 --- a/src/components/shortcuts.js +++ b/src/components/shortcuts.js @@ -5,10 +5,10 @@ * @module components/shortcuts */ -import playbackManager from './playback/playbackmanager'; +import { playbackManager } from './playback/playbackmanager'; import inputManager from '../scripts/inputManager'; -import connectionManager from 'jellyfin-apiclient'; -import appRouter from './appRouter'; +import { ConnectionManager } from 'jellyfin-apiclient'; +import { appRouter } from './appRouter'; import globalize from '../scripts/globalize'; import dom from '../scripts/dom'; import recordingHelper from './recordingcreator/recordinghelper'; @@ -82,7 +82,7 @@ import recordingHelper from './recordingcreator/recordinghelper'; const id = button.getAttribute('data-id'); const type = button.getAttribute('data-type'); - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); if (type === 'Timer') { return apiClient.getLiveTvTimer(id); @@ -112,7 +112,7 @@ import recordingHelper from './recordingcreator/recordinghelper'; } import('./itemContextMenu').then((itemContextMenu) => { - window.connectionManager.getApiClient(item.ServerId).getCurrentUser().then(user => { + ConnectionManager.getApiClient(item.ServerId).getCurrentUser().then(user => { itemContextMenu.show(Object.assign({ item: item, play: true, @@ -281,7 +281,7 @@ import recordingHelper from './recordingcreator/recordinghelper'; } function playTrailer(item) { - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); apiClient.getLocalTrailers(apiClient.getCurrentUserId(), item.Id).then(trailers => { playbackManager.play({ items: trailers }); @@ -289,7 +289,7 @@ import recordingHelper from './recordingcreator/recordinghelper'; } function editItem(item, serverId) { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); return new Promise((resolve, reject) => { const serverId = apiClient.serverInfo().Id; diff --git a/src/components/slideshow/slideshow.js b/src/components/slideshow/slideshow.js index a33e06b27c..4b8a4929b3 100644 --- a/src/components/slideshow/slideshow.js +++ b/src/components/slideshow/slideshow.js @@ -4,11 +4,11 @@ */ import dialogHelper from '../dialogHelper/dialogHelper'; import inputManager from '../../scripts/inputManager'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import layoutManager from '../layoutManager'; import focusManager from '../focusManager'; import browser from '../../scripts/browser'; -import appHost from '../apphost'; +import { appHost } from '../apphost'; import dom from '../../scripts/dom'; import './style.css'; import 'material-design-icons-iconfont'; @@ -85,7 +85,7 @@ function getBackdropImageUrl(item, options, apiClient) { * @returns {string} URL of the item's image. */ function getImgUrl(item, user) { - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); const imageOptions = {}; if (item.BackdropImageTags && item.BackdropImageTags.length) { diff --git a/src/components/subtitleeditor/subtitleeditor.js b/src/components/subtitleeditor/subtitleeditor.js index 6a53b4f54f..c3c174ea88 100644 --- a/src/components/subtitleeditor/subtitleeditor.js +++ b/src/components/subtitleeditor/subtitleeditor.js @@ -3,7 +3,7 @@ import dialogHelper from '../dialogHelper/dialogHelper'; import layoutManager from '../layoutManager'; import globalize from '../../scripts/globalize'; import * as userSettings from '../../scripts/settings/userSettings'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import loading from '../loading/loading'; import focusManager from '../focusManager'; import dom from '../../scripts/dom'; @@ -22,7 +22,7 @@ let hasChanges; function downloadRemoteSubtitles(context, id) { const url = 'Items/' + currentItem.Id + '/RemoteSearch/Subtitles/' + id; - const apiClient = window.connectionManager.getApiClient(currentItem.ServerId); + const apiClient = ConnectionManager.getApiClient(currentItem.ServerId); apiClient.ajax({ type: 'POST', @@ -56,7 +56,7 @@ function deleteLocalSubtitle(context, index) { const itemId = currentItem.Id; const url = 'Videos/' + itemId + '/Subtitles/' + index; - const apiClient = window.connectionManager.getApiClient(currentItem.ServerId); + const apiClient = ConnectionManager.getApiClient(currentItem.ServerId); apiClient.ajax({ @@ -244,7 +244,7 @@ function searchForSubtitles(context, language) { loading.show(); - const apiClient = window.connectionManager.getApiClient(currentItem.ServerId); + const apiClient = ConnectionManager.getApiClient(currentItem.ServerId); const url = apiClient.getUrl('Items/' + currentItem.Id + '/RemoteSearch/Subtitles/' + language); apiClient.getJSON(url).then(function (results) { @@ -357,7 +357,7 @@ function centerFocus(elem, horiz, on) { function showEditorInternal(itemId, serverId, template) { hasChanges = false; - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); return apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) { const dialogOptions = { removeOnClose: true, diff --git a/src/components/subtitlesettings/subtitlesettings.js b/src/components/subtitlesettings/subtitlesettings.js index 3462d9542e..082781d8be 100644 --- a/src/components/subtitlesettings/subtitlesettings.js +++ b/src/components/subtitlesettings/subtitlesettings.js @@ -1,14 +1,13 @@ import globalize from '../../scripts/globalize'; -import appHost from '../apphost'; +import { appHost } from '../apphost'; import appSettings from '../../scripts/settings/appSettings'; import focusManager from '../focusManager'; import layoutManager from '../layoutManager'; import loading from '../loading/loading'; -import connectionManager from 'jellyfin-apiclient'; import subtitleAppearanceHelper from './subtitleappearancehelper'; import settingsHelper from '../settingshelper'; import dom from '../../scripts/dom'; -import events from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import '../listview/listview.css'; import '../../elements/emby-select/emby-select'; import '../../elements/emby-slider/emby-slider'; @@ -232,7 +231,7 @@ export class SubtitleSettings { loading.show(); const userId = self.options.userId; - const apiClient = window.connectionManager.getApiClient(self.options.serverId); + const apiClient = ConnectionManager.getApiClient(self.options.serverId); const userSettings = self.options.userSettings; apiClient.getUser(userId).then(function (user) { @@ -256,7 +255,7 @@ export class SubtitleSettings { onSubmit(e) { const self = this; - const apiClient = window.connectionManager.getApiClient(self.options.serverId); + const apiClient = ConnectionManager.getApiClient(self.options.serverId); const userId = self.options.userId; const userSettings = self.options.userSettings; diff --git a/src/components/subtitlesync/subtitlesync.js b/src/components/subtitlesync/subtitlesync.js index c6d38d2f5c..d3477932c3 100644 --- a/src/components/subtitlesync/subtitlesync.js +++ b/src/components/subtitlesync/subtitlesync.js @@ -1,5 +1,5 @@ -import playbackManager from '../playback/playbackmanager'; +import { playbackManager } from '../playback/playbackmanager'; import layoutManager from '../layoutManager'; import template from './subtitlesync.template.html'; import './subtitlesync.css'; diff --git a/src/components/syncPlay/groupSelectionMenu.js b/src/components/syncPlay/groupSelectionMenu.js index 8882548e99..9269a584c7 100644 --- a/src/components/syncPlay/groupSelectionMenu.js +++ b/src/components/syncPlay/groupSelectionMenu.js @@ -1,6 +1,5 @@ -import events from 'jellyfin-apiclient'; -import connectionManager from 'jellyfin-apiclient'; -import playbackManager from '../playback/playbackmanager'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; +import { playbackManager } from '../playback/playbackmanager'; import syncPlayManager from './syncPlayManager'; import loading from '../loading/loading'; import toast from '../toast/toast'; @@ -172,8 +171,8 @@ export default function show (button) { }); }); - const apiClient = window.connectionManager.currentApiClient(); - window.connectionManager.user(apiClient).then((user) => { + const apiClient = ConnectionManager.currentApiClient(); + ConnectionManager.user(apiClient).then((user) => { if (syncPlayEnabled) { showLeaveGroupSelection(button, user, apiClient); } else { diff --git a/src/components/syncPlay/syncPlayManager.js b/src/components/syncPlay/syncPlayManager.js index 3a9b6e8891..0ff6ad3461 100644 --- a/src/components/syncPlay/syncPlayManager.js +++ b/src/components/syncPlay/syncPlayManager.js @@ -3,9 +3,8 @@ * @module components/syncPlay/syncPlayManager */ -import events from 'jellyfin-apiclient'; -import connectionManager from 'jellyfin-apiclient'; -import playbackManager from '../playback/playbackmanager'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; +import { playbackManager } from '../playback/playbackmanager'; import timeSyncManager from './timeSyncManager'; import toast from '../toast/toast'; import globalize from '../../scripts//globalize'; @@ -128,7 +127,7 @@ class SyncPlayManager { // Report ping if (this.syncEnabled) { - const apiClient = window.connectionManager.currentApiClient(); + const apiClient = ConnectionManager.currentApiClient(); const sessionId = getActivePlayerId(); if (!sessionId) { @@ -660,7 +659,7 @@ class SyncPlayManager { * Overrides PlaybackManager's unpause method. */ playRequest (player) { - const apiClient = window.connectionManager.currentApiClient(); + const apiClient = ConnectionManager.currentApiClient(); apiClient.requestSyncPlayStart(); } @@ -668,7 +667,7 @@ class SyncPlayManager { * Overrides PlaybackManager's pause method. */ pauseRequest (player) { - const apiClient = window.connectionManager.currentApiClient(); + const apiClient = ConnectionManager.currentApiClient(); apiClient.requestSyncPlayPause(); // Pause locally as well, to give the user some little control playbackManager._localUnpause(player); @@ -678,7 +677,7 @@ class SyncPlayManager { * Overrides PlaybackManager's seek method. */ seekRequest (PositionTicks, player) { - const apiClient = window.connectionManager.currentApiClient(); + const apiClient = ConnectionManager.currentApiClient(); apiClient.requestSyncPlaySeek({ PositionTicks: PositionTicks }); diff --git a/src/components/syncPlay/timeSyncManager.js b/src/components/syncPlay/timeSyncManager.js index d824b2e1d1..a39b06968e 100644 --- a/src/components/syncPlay/timeSyncManager.js +++ b/src/components/syncPlay/timeSyncManager.js @@ -3,8 +3,7 @@ * @module components/syncPlay/timeSyncManager */ -import events from 'jellyfin-apiclient'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; /** * Time estimation @@ -114,7 +113,7 @@ class TimeSyncManager { if (!this.poller) { this.poller = setTimeout(() => { this.poller = null; - const apiClient = window.connectionManager.currentApiClient(); + const apiClient = ConnectionManager.currentApiClient(); const requestSent = new Date(); apiClient.getServerTime().then((response) => { const responseReceived = new Date(); diff --git a/src/components/themeMediaPlayer.js b/src/components/themeMediaPlayer.js index b1b382e9b0..164d144d49 100644 --- a/src/components/themeMediaPlayer.js +++ b/src/components/themeMediaPlayer.js @@ -1,6 +1,6 @@ -import playbackManager from './playback/playbackmanager'; +import { playbackManager } from './playback/playbackmanager'; import * as userSettings from '../scripts/settings/userSettings'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; let currentOwnerId; let currentThemeIds = []; @@ -62,7 +62,7 @@ function loadThemeMedia(item) { return; } - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); apiClient.getThemeMedia(apiClient.getCurrentUserId(), item.Id, true).then(function (themeMediaResult) { const ownerId = themeMediaResult.ThemeVideosResult.Items.length ? themeMediaResult.ThemeVideosResult.OwnerId : themeMediaResult.ThemeSongsResult.OwnerId; diff --git a/src/components/tunerPicker.js b/src/components/tunerPicker.js index e2793bf9d6..d47b768d89 100644 --- a/src/components/tunerPicker.js +++ b/src/components/tunerPicker.js @@ -1,7 +1,7 @@ import dialogHelper from './dialogHelper/dialogHelper'; import dom from '../scripts/dom'; import layoutManager from './layoutManager'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import globalize from '../scripts/globalize'; import loading from './loading/loading'; import browser from '../scripts/browser'; @@ -163,7 +163,7 @@ function tunerPicker() { scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false); } - const apiClient = window.connectionManager.getApiClient(options.serverId); + const apiClient = ConnectionManager.getApiClient(options.serverId); discoverDevices(dlg, apiClient); if (layoutManager.tv) { diff --git a/src/components/upnextdialog/upnextdialog.js b/src/components/upnextdialog/upnextdialog.js index 9515e2ef36..a7f6ac21d2 100644 --- a/src/components/upnextdialog/upnextdialog.js +++ b/src/components/upnextdialog/upnextdialog.js @@ -1,7 +1,6 @@ import dom from '../../scripts/dom'; -import playbackManager from '../playback/playbackmanager'; -import connectionManager from 'jellyfin-apiclient'; -import events from 'jellyfin-apiclient'; +import { playbackManager } from '../playback/playbackmanager'; +import { events } from 'jellyfin-apiclient'; import mediaInfo from '../mediainfo/mediainfo'; import layoutManager from '../layoutManager'; import focusManager from '../focusManager'; diff --git a/src/components/userdatabuttons/userdatabuttons.js b/src/components/userdatabuttons/userdatabuttons.js index cd906e3bb2..d9edda5054 100644 --- a/src/components/userdatabuttons/userdatabuttons.js +++ b/src/components/userdatabuttons/userdatabuttons.js @@ -1,4 +1,4 @@ -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import globalize from '../../scripts/globalize'; import dom from '../../scripts/dom'; import itemHelper from '../itemHelper'; @@ -188,12 +188,12 @@ function markPlayed(link) { } function likes(id, serverId, isLiked) { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); return apiClient.updateUserItemRating(apiClient.getCurrentUserId(), id, isLiked); } function played(id, serverId, isPlayed) { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); const method = isPlayed ? 'markPlayed' : 'markUnplayed'; @@ -201,13 +201,13 @@ function played(id, serverId, isPlayed) { } function favorite(id, serverId, isFavorite) { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); return apiClient.updateFavoriteStatus(apiClient.getCurrentUserId(), id, isFavorite); } function clearLike(id, serverId) { - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); return apiClient.clearUserItemRating(apiClient.getCurrentUserId(), id); } diff --git a/src/components/viewManager/viewManager.js b/src/components/viewManager/viewManager.js index cfcd67cf89..91212e2cc6 100644 --- a/src/components/viewManager/viewManager.js +++ b/src/components/viewManager/viewManager.js @@ -1,6 +1,5 @@ import viewContainer from '../viewContainer'; import focusManager from '../focusManager'; -import queryString from 'query-string'; import layoutManager from '../layoutManager'; let currentView; @@ -101,7 +100,7 @@ function dispatchViewEvent(view, eventInfo, eventName, isCancellable) { function getViewEventDetail(view, options, isRestore) { const url = options.url; const index = url.indexOf('?'); - const params = index === -1 ? {} : queryString.parse(url.substring(index + 1)); + const params = new URLSearchParams(url.substring(index + 1)); return { detail: { diff --git a/src/controllers/dashboard/dashboard.js b/src/controllers/dashboard/dashboard.js index 692cc020b8..e5a34eadcb 100644 --- a/src/controllers/dashboard/dashboard.js +++ b/src/controllers/dashboard/dashboard.js @@ -1,5 +1,5 @@ import datetime from '../../scripts/datetime'; -import { connectionManager, events } from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import itemHelper from '../../components/itemHelper'; import serverNotifications from '../../scripts/serverNotifications'; import dom from '../../scripts/dom'; @@ -60,7 +60,7 @@ import taskButton from '../../scripts/taskbutton'; confirmText: globalize.translate('ButtonSend') }).then(function (text) { if (text) { - window.connectionManager.getApiClient(session.ServerId).sendMessageCommand(session.Id, { + ConnectionManager.getApiClient(session.ServerId).sendMessageCommand(session.Id, { Text: text, TimeoutMs: 5e3 }); @@ -73,7 +73,7 @@ import taskButton from '../../scripts/taskbutton'; import('../../components/actionSheet/actionSheet').then(({default: actionsheet}) => { const menuItems = []; - if (session.ServerId && session.DeviceId !== window.connectionManager.deviceId()) { + if (session.ServerId && session.DeviceId !== ConnectionManager.deviceId()) { menuItems.push({ name: globalize.translate('SendMessage'), id: 'sendmessage' @@ -123,9 +123,9 @@ import taskButton from '../../scripts/taskbutton'; } else if (btn.classList.contains('btnSessionSendMessage')) { showSendMessageForm(btn, session); } else if (btn.classList.contains('btnSessionStop')) { - window.connectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id, 'Stop'); + ConnectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id, 'Stop'); } else if (btn.classList.contains('btnSessionPlayPause') && session.PlayState) { - window.connectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id, 'PlayPause'); + ConnectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id, 'PlayPause'); } } } @@ -313,7 +313,7 @@ import taskButton from '../../scripts/taskbutton'; btnCssClass = session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length ? '' : ' hide'; html += ''; - btnCssClass = session.ServerId && session.SupportedCommands.indexOf('DisplayMessage') !== -1 && session.DeviceId !== window.connectionManager.deviceId() ? '' : ' hide'; + btnCssClass = session.ServerId && session.SupportedCommands.indexOf('DisplayMessage') !== -1 && session.DeviceId !== ConnectionManager.deviceId() ? '' : ' hide'; html += ''; html += '
'; diff --git a/src/controllers/dashboard/scheduledtasks/scheduledtasks.js b/src/controllers/dashboard/scheduledtasks/scheduledtasks.js index 436a06b746..7c35bf1fca 100644 --- a/src/controllers/dashboard/scheduledtasks/scheduledtasks.js +++ b/src/controllers/dashboard/scheduledtasks/scheduledtasks.js @@ -1,6 +1,6 @@ import 'jquery'; import loading from '../../../components/loading/loading'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import globalize from '../../../scripts/globalize'; import serverNotifications from '../../../scripts/serverNotifications'; import { formatDistance, formatDistanceToNow } from 'date-fns'; diff --git a/src/controllers/favorites.js b/src/controllers/favorites.js index 01cd75e6e8..41372aa213 100644 --- a/src/controllers/favorites.js +++ b/src/controllers/favorites.js @@ -1,9 +1,9 @@ -import appRouter from '../components/appRouter'; +import { appRouter } from '../components/appRouter'; import cardBuilder from '../components/cardbuilder/cardBuilder'; import dom from '../scripts/dom'; import globalize from '../scripts/globalize'; -import connectionManager from 'jellyfin-apiclient'; -import appHost from '../components/apphost'; +import { ConnectionManager } from 'jellyfin-apiclient'; +import { appHost } from '../components/apphost'; import layoutManager from '../components/layoutManager'; import focusManager from '../components/focusManager'; import '../elements/emby-itemscontainer/emby-itemscontainer'; @@ -270,7 +270,7 @@ class FavoritesTab { constructor(view, params) { this.view = view; this.params = params; - this.apiClient = window.connectionManager.currentApiClient(); + this.apiClient = ConnectionManager.currentApiClient(); this.sectionsContainer = view.querySelector('.sections'); createSections(this, this.sectionsContainer, this.apiClient); } diff --git a/src/controllers/home.js b/src/controllers/home.js index 56ad481262..ed447cac8f 100644 --- a/src/controllers/home.js +++ b/src/controllers/home.js @@ -44,15 +44,15 @@ class HomeView extends TabbedView { switch (index) { case 0: - depends = 'controllers/hometab'; + depends = 'hometab'; break; case 1: - depends = 'controllers/favorites'; + depends = 'favorites'; } const instance = this; - return import(depends).then(({ default: controllerFactory }) => { + return import(/* webpackChunkName: "[request]" */ `../controllers/${depends}`).then(({ default: controllerFactory }) => { let controller = instance.tabControllers[index]; if (!controller) { diff --git a/src/controllers/hometab.js b/src/controllers/hometab.js index 65047dbaa8..d1e18b42c3 100644 --- a/src/controllers/hometab.js +++ b/src/controllers/hometab.js @@ -1,6 +1,5 @@ import * as userSettings from '../scripts/settings/userSettings'; import loading from '../components/loading/loading'; -import connectionManager from 'jellyfin-apiclient'; import focusManager from '../components/focusManager'; import homeSections from '../components/homesections/homesections'; import '../elements/emby-itemscontainer/emby-itemscontainer'; @@ -9,7 +8,7 @@ class HomeTab { constructor(view, params) { this.view = view; this.params = params; - this.apiClient = window.connectionManager.currentApiClient(); + this.apiClient = window.ConnectionManager.currentApiClient(); this.sectionsContainer = view.querySelector('.sections'); view.querySelector('.sections').addEventListener('settingschange', onHomeScreenSettingsChanged.bind(this)); } diff --git a/src/controllers/itemDetails/index.js b/src/controllers/itemDetails/index.js index 16a77076a5..02da9460c7 100644 --- a/src/controllers/itemDetails/index.js +++ b/src/controllers/itemDetails/index.js @@ -1,8 +1,8 @@ -import appHost from '../../components/apphost'; +import { appHost } from '../../components/apphost'; import loading from '../../components/loading/loading'; -import appRouter from '../../components/appRouter'; +import { appRouter } from '../../components/appRouter'; import layoutManager from '../../components/layoutManager'; -import { connectionManager, events } from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import * as userSettings from '../../scripts/settings/userSettings'; import cardBuilder from '../../components/cardbuilder/cardBuilder'; import datetime from '../../scripts/datetime'; @@ -17,7 +17,7 @@ import imageLoader from '../../components/images/imageLoader'; import libraryMenu from '../../scripts/libraryMenu'; import globalize from '../../scripts/globalize'; import browser from '../../scripts/browser'; -import playbackManager from '../../components/playback/playbackmanager'; +import { playbackManager } from '../../components/playback/playbackmanager'; import '../../assets/css/scrollstyles.css'; import '../../elements/emby-itemscontainer/emby-itemscontainer'; import '../../elements/emby-checkbox/emby-checkbox'; @@ -563,7 +563,7 @@ function renderDetailPageBackdrop(page, item, apiClient) { } function reloadFromItem(instance, page, params, item, user) { - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); Emby.Page.setTitle(''); @@ -805,7 +805,7 @@ function renderNextUp(page, item, user) { return void section.classList.add('hide'); } - window.connectionManager.getApiClient(item.ServerId).getNextUpEpisodes({ + ConnectionManager.getApiClient(item.ServerId).getNextUpEpisodes({ SeriesId: item.Id, UserId: user.Id }).then(function (result) { @@ -1209,7 +1209,7 @@ function renderSimilarItems(page, item, context) { } similarCollapsible.classList.remove('hide'); - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); const options = { userId: apiClient.getCurrentUserId(), limit: 12, @@ -1323,7 +1323,7 @@ function renderChildren(page, item) { } let promise; - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); const userId = apiClient.getCurrentUserId(); if (item.Type == 'Series') { @@ -1571,7 +1571,7 @@ function renderChannelGuide(page, apiClient, item) { } function renderSeriesSchedule(page, item) { - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); apiClient.getLiveTvPrograms({ UserId: apiClient.getCurrentUserId(), HasAired: false, @@ -1731,7 +1731,7 @@ function renderCollectionItemType(page, parentItem, type, items) { } function renderMusicVideos(page, item, user) { - window.connectionManager.getApiClient(item.ServerId).getItems(user.Id, { + ConnectionManager.getApiClient(item.ServerId).getItems(user.Id, { SortBy: 'SortName', SortOrder: 'Ascending', IncludeItemTypes: 'MusicVideo', @@ -1751,7 +1751,7 @@ function renderMusicVideos(page, item, user) { } function renderAdditionalParts(page, item, user) { - window.connectionManager.getApiClient(item.ServerId).getAdditionalVideoParts(user.Id, item.Id).then(function (result) { + ConnectionManager.getApiClient(item.ServerId).getAdditionalVideoParts(user.Id, item.Id).then(function (result) { if (result.Items.length) { page.querySelector('#additionalPartsCollapsible').classList.remove('hide'); const additionalPartsContent = page.querySelector('#additionalPartsContent'); @@ -1796,7 +1796,7 @@ function getVideosHtml(items) { } function renderSpecials(page, item, user) { - window.connectionManager.getApiClient(item.ServerId).getSpecialFeatures(user.Id, item.Id).then(function (specials) { + ConnectionManager.getApiClient(item.ServerId).getSpecialFeatures(user.Id, item.Id).then(function (specials) { const specialsContent = page.querySelector('#specialsContent'); specialsContent.innerHTML = getVideosHtml(specials); imageLoader.lazyChildren(specialsContent); @@ -1852,7 +1852,7 @@ export default function (view, params) { function reload(instance, page, params) { loading.show(); - const apiClient = params.serverId ? window.connectionManager.getApiClient(params.serverId) : ApiClient; + const apiClient = params.serverId ? ConnectionManager.getApiClient(params.serverId) : ApiClient; Promise.all([getPromise(apiClient, params), apiClient.getCurrentUser()]).then(([item, user]) => { currentItem = item; @@ -1901,7 +1901,7 @@ export default function (view, params) { const item = currentItem; if (item.Type === 'Program') { - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); return void apiClient.getLiveTvChannel(item.ChannelId, apiClient.getCurrentUserId()).then(function (channel) { playbackManager.play({ items: [channel] @@ -1938,7 +1938,7 @@ export default function (view, params) { function onCancelTimerClick() { import('../../components/recordingcreator/recordinghelper').then(({ default: recordingHelper }) => { - recordingHelper.cancelTimer(window.connectionManager.getApiClient(currentItem.ServerId), currentItem.TimerId).then(function () { + recordingHelper.cancelTimer(ConnectionManager.getApiClient(currentItem.ServerId), currentItem.TimerId).then(function () { reload(self, view, params); }); }); @@ -2002,7 +2002,7 @@ export default function (view, params) { let currentItem; const self = this; - const apiClient = params.serverId ? window.connectionManager.getApiClient(params.serverId) : ApiClient; + const apiClient = params.serverId ? ConnectionManager.getApiClient(params.serverId) : ApiClient; const btnResume = view.querySelector('.mainDetailButtons .btnResume'); const btnPlay = view.querySelector('.mainDetailButtons .btnPlay'); diff --git a/src/controllers/list.js b/src/controllers/list.js index d356d800a3..a18fbeb7fc 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -5,9 +5,9 @@ import * as userSettings from '../scripts/settings/userSettings'; import focusManager from '../components/focusManager'; import cardBuilder from '../components/cardbuilder/cardBuilder'; import loading from '../components/loading/loading'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import AlphaNumericShortcuts from '../scripts/alphanumericshortcuts'; -import playbackManager from '../components/playback/playbackmanager'; +import { playbackManager } from '../components/playback/playbackmanager'; import AlphaPicker from '../components/alphaPicker/alphaPicker'; import '../elements/emby-itemscontainer/emby-itemscontainer'; import '../elements/emby-scroller/emby-scroller'; @@ -16,7 +16,7 @@ import '../elements/emby-scroller/emby-scroller'; function getInitialLiveTvQuery(instance, params) { const query = { - UserId: window.connectionManager.getApiClient(params.serverId).getCurrentUserId(), + UserId: ConnectionManager.getApiClient(params.serverId).getCurrentUserId(), StartIndex: 0, Fields: 'ChannelInfo,PrimaryImageAspectRatio', Limit: 300 @@ -232,7 +232,7 @@ import '../elements/emby-scroller/emby-scroller'; } function getItems(instance, params, item, sortBy, startIndex, limit) { - const apiClient = window.connectionManager.getApiClient(params.serverId); + const apiClient = ConnectionManager.getApiClient(params.serverId); instance.queryRecursive = false; if (params.type === 'Recordings') { @@ -333,7 +333,7 @@ import '../elements/emby-scroller/emby-scroller'; return Promise.resolve(null); } - const apiClient = window.connectionManager.getApiClient(params.serverId); + const apiClient = ConnectionManager.getApiClient(params.serverId); const itemId = params.genreId || params.musicGenreId || params.studioId || params.personId || params.parentId; if (itemId) { diff --git a/src/controllers/livetv/livetvchannels.js b/src/controllers/livetv/livetvchannels.js index 9de6e71785..4ab1f45ed9 100644 --- a/src/controllers/livetv/livetvchannels.js +++ b/src/controllers/livetv/livetvchannels.js @@ -2,7 +2,7 @@ import cardBuilder from '../../components/cardbuilder/cardBuilder'; import imageLoader from '../../components/images/imageLoader'; import libraryBrowser from '../../scripts/libraryBrowser'; import loading from '../../components/loading/loading'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import * as userSettings from '../../scripts/settings/userSettings'; import '../../elements/emby-itemscontainer/emby-itemscontainer'; diff --git a/src/controllers/livetvguideprovider.js b/src/controllers/livetvguideprovider.js index 750bbff479..59a19d599b 100644 --- a/src/controllers/livetvguideprovider.js +++ b/src/controllers/livetvguideprovider.js @@ -1,4 +1,4 @@ -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import loading from '../components/loading/loading'; import globalize from '../scripts/globalize'; diff --git a/src/controllers/movies/moviegenres.js b/src/controllers/movies/moviegenres.js index 2b106dc361..153cc64945 100644 --- a/src/controllers/movies/moviegenres.js +++ b/src/controllers/movies/moviegenres.js @@ -4,7 +4,7 @@ import libraryBrowser from '../../scripts/libraryBrowser'; import cardBuilder from '../../components/cardbuilder/cardBuilder'; import lazyLoader from '../../components/lazyLoader/lazyLoaderIntersectionObserver'; import globalize from '../../scripts/globalize'; -import appRouter from '../../components/appRouter'; +import { appRouter } from '../../components/appRouter'; import '../../elements/emby-button/emby-button'; /* eslint-disable indent */ diff --git a/src/controllers/movies/movies.js b/src/controllers/movies/movies.js index 648290abe1..736489d3d2 100644 --- a/src/controllers/movies/movies.js +++ b/src/controllers/movies/movies.js @@ -1,6 +1,6 @@ import loading from '../../components/loading/loading'; import * as userSettings from '../../scripts/settings/userSettings'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import libraryBrowser from '../../scripts/libraryBrowser'; import { AlphaPicker } from '../../components/alphaPicker/alphaPicker'; import listView from '../../components/listview/listview'; diff --git a/src/controllers/movies/moviesrecommended.js b/src/controllers/movies/moviesrecommended.js index 1270e9f134..0c02e7c010 100644 --- a/src/controllers/movies/moviesrecommended.js +++ b/src/controllers/movies/moviesrecommended.js @@ -1,5 +1,5 @@ -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import layoutManager from '../../components/layoutManager'; import inputManager from '../../scripts/inputManager'; import * as userSettings from '../../scripts/settings/userSettings'; @@ -8,7 +8,7 @@ import * as mainTabsManager from '../../components/maintabsmanager'; import cardBuilder from '../../components/cardbuilder/cardBuilder'; import dom from '../../scripts/dom'; import imageLoader from '../../components/images/imageLoader'; -import playbackManager from '../../components/playback/playbackmanager'; +import { playbackManager } from '../../components/playback/playbackmanager'; import globalize from '../../scripts/globalize'; import '../../elements/emby-scroller/emby-scroller'; import '../../elements/emby-itemscontainer/emby-itemscontainer'; diff --git a/src/controllers/movies/movietrailers.js b/src/controllers/movies/movietrailers.js index 4f92b139bc..92be37720d 100644 --- a/src/controllers/movies/movietrailers.js +++ b/src/controllers/movies/movietrailers.js @@ -1,5 +1,5 @@ import loading from '../../components/loading/loading'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import libraryBrowser from '../../scripts/libraryBrowser'; import imageLoader from '../../components/images/imageLoader'; import { AlphaPicker } from '../../components/alphaPicker/alphaPicker'; diff --git a/src/controllers/music/musicalbums.js b/src/controllers/music/musicalbums.js index d9abe48fe7..32eb38a84e 100644 --- a/src/controllers/music/musicalbums.js +++ b/src/controllers/music/musicalbums.js @@ -1,6 +1,6 @@ -import playbackManager from '../../components/playback/playbackmanager'; +import { playbackManager } from '../../components/playback/playbackmanager'; import loading from '../../components/loading/loading'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import libraryBrowser from '../../scripts/libraryBrowser'; import imageLoader from '../../components/images/imageLoader'; import AlphaPicker from '../../components/alphaPicker/alphaPicker'; diff --git a/src/controllers/music/musicartists.js b/src/controllers/music/musicartists.js index a7c01220cd..232b2fdd13 100644 --- a/src/controllers/music/musicartists.js +++ b/src/controllers/music/musicartists.js @@ -1,5 +1,5 @@ import loading from '../../components/loading/loading'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import libraryBrowser from '../../scripts/libraryBrowser'; import imageLoader from '../../components/images/imageLoader'; import { AlphaPicker } from '../../components/alphaPicker/alphaPicker'; diff --git a/src/controllers/music/songs.js b/src/controllers/music/songs.js index cc526df6b4..133d9bdab3 100644 --- a/src/controllers/music/songs.js +++ b/src/controllers/music/songs.js @@ -1,5 +1,5 @@ -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import libraryBrowser from '../../scripts/libraryBrowser'; import imageLoader from '../../components/images/imageLoader'; import listView from '../../components/listview/listview'; diff --git a/src/controllers/playback/video/index.js b/src/controllers/playback/video/index.js index 5e99971a84..9d531bfdcc 100644 --- a/src/controllers/playback/video/index.js +++ b/src/controllers/playback/video/index.js @@ -1,4 +1,4 @@ -import playbackManager from '../../../components/playback/playbackmanager'; +import { playbackManager } from '../../../components/playback/playbackmanager'; import dom from '../../../scripts/dom'; import inputManager from '../../../scripts/inputManager'; import mouseManager from '../../../scripts/mouseManager'; @@ -6,10 +6,10 @@ import datetime from '../../../scripts/datetime'; import itemHelper from '../../../components/itemHelper'; import mediaInfo from '../../../components/mediainfo/mediainfo'; import focusManager from '../../../components/focusManager'; -import { connectionManager, events } from 'jellyfin-apiclient';; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import browser from '../../../scripts/browser'; import globalize from '../../../scripts/globalize'; -import appHost from '../../../components/apphost'; +import { appHost } from '../../../components/apphost'; import layoutManager from '../../../components/layoutManager'; import * as userSettings from '../../../scripts/settings/userSettings'; import keyboardnavigation from '../../../scripts/keyboardNavigation'; @@ -73,7 +73,7 @@ import '../../../assets/css/videoosd.css'; function getDisplayItem(item) { if (item.Type === 'TvChannel') { - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); return apiClient.getItem(apiClient.getCurrentUserId(), item.Id).then(function (refreshedItem) { return { originalItem: refreshedItem, @@ -97,7 +97,7 @@ import '../../../assets/css/videoosd.css'; return void view.querySelector('.btnRecord').classList.add('hide'); } - window.connectionManager.getApiClient(item.ServerId).getCurrentUser().then(function (user) { + ConnectionManager.getApiClient(item.ServerId).getCurrentUser().then(function (user) { if (user.Policy.EnableLiveTvManagement) { import('../../../components/recordingcreator/recordingbutton').then((RecordingButton) => { if (recordingButtonManager) { @@ -1515,7 +1515,7 @@ import '../../../assets/css/videoosd.css'; const item = currentItem; if (item && item.Chapters && item.Chapters.length && item.Chapters[0].ImageTag) { - const html = getChapterBubbleHtml(window.connectionManager.getApiClient(item.ServerId), item, item.Chapters, ticks); + const html = getChapterBubbleHtml(ConnectionManager.getApiClient(item.ServerId), item, item.Chapters, ticks); if (html) { return html; diff --git a/src/controllers/searchpage.js b/src/controllers/searchpage.js index 9b40f6a064..f8cfce3731 100644 --- a/src/controllers/searchpage.js +++ b/src/controllers/searchpage.js @@ -1,6 +1,6 @@ import SearchFields from '../components/search/searchfields'; import SearchResults from '../components/search/searchresults'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; export default function (view, params) { function onSearch(e, value) { diff --git a/src/controllers/session/login/index.js b/src/controllers/session/login/index.js index 4aef28b17d..e1ac1d1259 100644 --- a/src/controllers/session/login/index.js +++ b/src/controllers/session/login/index.js @@ -1,7 +1,7 @@ -import appHost from '../../../components/apphost'; +import { appHost } from '../../../components/apphost'; import appSettings from '../../../scripts/settings/appSettings'; import dom from '../../../scripts/dom'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import loading from '../../../components/loading/loading'; import layoutManager from '../../../components/layoutManager'; import libraryMenu from '../../../scripts/libraryMenu'; @@ -192,7 +192,7 @@ import '../../../elements/emby-checkbox/emby-checkbox'; const serverId = params.serverid; if (serverId) { - return window.connectionManager.getOrCreateApiClient(serverId); + return ConnectionManager.getOrCreateApiClient(serverId); } return ApiClient; diff --git a/src/controllers/session/selectServer/index.js b/src/controllers/session/selectServer/index.js index 721cc8c106..accc828ba4 100644 --- a/src/controllers/session/selectServer/index.js +++ b/src/controllers/session/selectServer/index.js @@ -1,10 +1,10 @@ import loading from '../../../components/loading/loading'; -import appRouter from '../../../components/appRouter'; +import { appRouter } from '../../../components/appRouter'; import layoutManager from '../../../components/layoutManager'; import libraryMenu from '../../../scripts/libraryMenu'; import appSettings from '../../../scripts/settings/appSettings'; import focusManager from '../../../components/focusManager'; -import connectionManager from 'jellyfin-apiclient'; +import { ConnectionManager } from 'jellyfin-apiclient'; import globalize from '../../../scripts/globalize'; import actionSheet from '../../../components/actionSheet/actionSheet'; import dom from '../../../scripts/dom'; @@ -113,7 +113,7 @@ import '../../../elements/emby-button/emby-button'; export default function (view, params) { function connectToServer(server) { loading.show(); - window.connectionManager.connectToServer(server, { + ConnectionManager.connectToServer(server, { enableAutoLogin: appSettings.enableAutoLogin() }).then(function (result) { loading.hide(); @@ -145,7 +145,7 @@ import '../../../elements/emby-button/emby-button'; function deleteServer(server) { loading.show(); - window.connectionManager.deleteServer(server.Id).then(function () { + ConnectionManager.deleteServer(server.Id).then(function () { loading.hide(); loadServers(); }); @@ -187,7 +187,7 @@ import '../../../elements/emby-button/emby-button'; function loadServers() { loading.show(); - window.connectionManager.getAvailableServers().then(onServersRetrieved); + ConnectionManager.getAvailableServers().then(onServersRetrieved); } let servers; diff --git a/src/controllers/shows/episodes.js b/src/controllers/shows/episodes.js index fb78c47b80..76c620f104 100644 --- a/src/controllers/shows/episodes.js +++ b/src/controllers/shows/episodes.js @@ -1,5 +1,5 @@ import loading from '../../components/loading/loading'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import libraryBrowser from '../../scripts/libraryBrowser'; import imageLoader from '../../components/images/imageLoader'; import listView from '../../components/listview/listview'; diff --git a/src/controllers/shows/tvgenres.js b/src/controllers/shows/tvgenres.js index 75e89ea9c9..82a15bb0c4 100644 --- a/src/controllers/shows/tvgenres.js +++ b/src/controllers/shows/tvgenres.js @@ -4,7 +4,7 @@ import libraryBrowser from '../../scripts/libraryBrowser'; import cardBuilder from '../../components/cardbuilder/cardBuilder'; import lazyLoader from '../../components/lazyLoader/lazyLoaderIntersectionObserver'; import globalize from '../../scripts/globalize'; -import appRouter from '../../components/appRouter'; +import { appRouter } from '../../components/appRouter'; import '../../elements/emby-button/emby-button'; /* eslint-disable indent */ diff --git a/src/controllers/shows/tvrecommended.js b/src/controllers/shows/tvrecommended.js index d778beebff..33cd666572 100644 --- a/src/controllers/shows/tvrecommended.js +++ b/src/controllers/shows/tvrecommended.js @@ -1,5 +1,5 @@ -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import inputManager from '../../scripts/inputManager'; import libraryMenu from '../../scripts/libraryMenu'; import layoutManager from '../../components/layoutManager'; @@ -7,7 +7,7 @@ import loading from '../../components/loading/loading'; import dom from '../../scripts/dom'; import * as userSettings from '../../scripts/settings/userSettings'; import cardBuilder from '../../components/cardbuilder/cardBuilder'; -import playbackManager from '../../components/playback/playbackmanager'; +import { playbackManager } from '../../components/playback/playbackmanager'; import * as mainTabsManager from '../../components/maintabsmanager'; import globalize from '../../scripts/globalize'; import '../../assets/css/scrollstyles.css'; diff --git a/src/controllers/shows/tvshows.js b/src/controllers/shows/tvshows.js index b59e5a2c4d..2fe940a060 100644 --- a/src/controllers/shows/tvshows.js +++ b/src/controllers/shows/tvshows.js @@ -1,5 +1,5 @@ import loading from '../../components/loading/loading'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import libraryBrowser from '../../scripts/libraryBrowser'; import imageLoader from '../../components/images/imageLoader'; import listView from '../../components/listview/listview'; diff --git a/src/controllers/user/menu/index.js b/src/controllers/user/menu/index.js index e480d02588..f3f92386e2 100644 --- a/src/controllers/user/menu/index.js +++ b/src/controllers/user/menu/index.js @@ -1,4 +1,4 @@ -import appHost from '../../../components/apphost'; +import { appHost } from '../../../components/apphost'; import '../../../components/listview/listview.css'; import '../../../elements/emby-button/emby-button'; import layoutManager from '../../../components/layoutManager'; diff --git a/src/controllers/user/profile/index.js b/src/controllers/user/profile/index.js index deedaf306c..113f08c4d8 100644 --- a/src/controllers/user/profile/index.js +++ b/src/controllers/user/profile/index.js @@ -1,7 +1,7 @@ import UserPasswordPage from '../../dashboard/users/userpasswordpage'; import loading from '../../../components/loading/loading'; import libraryMenu from '../../../scripts/libraryMenu'; -import appHost from '../../../components/apphost'; +import { appHost } from '../../../components/apphost'; import globalize from '../../../scripts/globalize'; import '../../../elements/emby-button/emby-button'; diff --git a/src/elements/emby-button/emby-button.js b/src/elements/emby-button/emby-button.js index 9eefbcbed4..e86901b9a3 100644 --- a/src/elements/emby-button/emby-button.js +++ b/src/elements/emby-button/emby-button.js @@ -1,12 +1,65 @@ import { removeEventListener, addEventListener } from '../../scripts/dom'; import layoutManager from '../../components/layoutManager'; import shell from '../../scripts/shell'; -import appRouter from '../../components/appRouter'; -import appHost from '../../components/apphost'; +import { appRouter } from '../../components/appRouter'; +import { appHost } from '../../components/apphost'; import './emby-button.css'; -const EmbyButtonPrototype = Object.create(HTMLButtonElement.prototype); -const EmbyLinkButtonPrototype = Object.create(HTMLAnchorElement.prototype); +class EmbyButton extends HTMLButtonElement { + createdCallback() { + if (this.classList.contains('emby-button')) { + return; + } + + this.classList.add('../../elements/emby-button/emby-button'); + // TODO replace all instances of element-showfocus with this method + if (layoutManager.tv) { + // handles all special css for tv layout + // this method utilizes class chaining + this.classList.add('show-focus'); + } + } + + attachedCallback() { + if (this.tagName === 'A') { + removeEventListener(this, 'click', onAnchorClick, {}); + addEventListener(this, 'click', onAnchorClick, {}); + + if (this.getAttribute('data-autohide') === 'true') { + if (appHost.supports('externallinks')) { + this.classList.remove('hide'); + } else { + this.classList.add('hide'); + } + } + } + } + + detachedCallback() { + removeEventListener(this, 'click', onAnchorClick, {}); + } +} + +class EmbyLinkButton extends HTMLAnchorElement { + attachedCallback() { + if (this.tagName === 'A') { + removeEventListener(this, 'click', onAnchorClick, {}); + addEventListener(this, 'click', onAnchorClick, {}); + + if (this.getAttribute('data-autohide') === 'true') { + if (appHost.supports('externallinks')) { + this.classList.remove('hide'); + } else { + this.classList.add('hide'); + } + } + } + } + + detachedCallback() { + removeEventListener(this, 'click', onAnchorClick, {}); + } +} function onAnchorClick(e) { const href = this.getAttribute('href') || ''; @@ -24,50 +77,8 @@ function onAnchorClick(e) { } } -EmbyButtonPrototype.createdCallback = function () { - if (this.classList.contains('emby-button')) { - return; - } +customElements.define('emby-button', EmbyButton, { extends: 'button' }); - this.classList.add('../../elements/emby-button/emby-button'); - // TODO replace all instances of element-showfocus with this method - if (layoutManager.tv) { - // handles all special css for tv layout - // this method utilizes class chaining - this.classList.add('show-focus'); - } -}; +customElements.define('emby-linkbutton', EmbyLinkButton, { extends: 'a' }); -EmbyButtonPrototype.attachedCallback = function () { - if (this.tagName === 'A') { - removeEventListener(this, 'click', onAnchorClick, {}); - addEventListener(this, 'click', onAnchorClick, {}); - - if (this.getAttribute('data-autohide') === 'true') { - if (appHost.supports('externallinks')) { - this.classList.remove('hide'); - } else { - this.classList.add('hide'); - } - } - } -}; - -EmbyButtonPrototype.detachedCallback = function () { - removeEventListener(this, 'click', onAnchorClick, {}); -}; - -EmbyLinkButtonPrototype.createdCallback = EmbyButtonPrototype.createdCallback; -EmbyLinkButtonPrototype.attachedCallback = EmbyButtonPrototype.attachedCallback; - -document.registerElement('../../elements/emby-button/emby-button', { - prototype: EmbyButtonPrototype, - extends: 'button' -}); - -document.registerElement('emby-linkbutton', { - prototype: EmbyLinkButtonPrototype, - extends: 'a' -}); - -export default EmbyButtonPrototype; +export default EmbyButton; diff --git a/src/elements/emby-itemrefreshindicator/emby-itemrefreshindicator.js b/src/elements/emby-itemrefreshindicator/emby-itemrefreshindicator.js index 0fd9eeb952..b71a5ab4ef 100644 --- a/src/elements/emby-itemrefreshindicator/emby-itemrefreshindicator.js +++ b/src/elements/emby-itemrefreshindicator/emby-itemrefreshindicator.js @@ -1,7 +1,7 @@ import EmbyProgressRing from '../emby-progressring/emby-progressring'; import dom from '../../scripts/dom'; import serverNotifications from '../../scripts/serverNotifications'; -import events from 'jellyfin-apiclient'; +import { events } from 'jellyfin-apiclient'; import 'webcomponents.js'; /* eslint-disable indent */ diff --git a/src/elements/emby-itemscontainer/emby-itemscontainer.js b/src/elements/emby-itemscontainer/emby-itemscontainer.js index 1f8b1607a1..eff9ba2550 100644 --- a/src/elements/emby-itemscontainer/emby-itemscontainer.js +++ b/src/elements/emby-itemscontainer/emby-itemscontainer.js @@ -1,8 +1,7 @@ import itemShortcuts from '../../components/shortcuts'; import inputManager from '../../scripts/inputManager'; -import connectionManager from 'jellyfin-apiclient'; -import playbackManager from '../../components/playback/playbackmanager'; +import { playbackManager } from '../../components/playback/playbackmanager'; import imageLoader from '../../components/images/imageLoader'; import layoutManager from '../../components/layoutManager'; import browser from '../../scripts/browser'; @@ -10,7 +9,7 @@ import dom from '../../scripts/dom'; import loading from '../../components/loading/loading'; import focusManager from '../../components/focusManager'; import serverNotifications from '../../scripts/serverNotifications'; -import events from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import 'webcomponents.js'; /* eslint-disable indent */ @@ -104,7 +103,7 @@ import 'webcomponents.js'; } const serverId = el.getAttribute('data-serverid'); - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); loading.show(); diff --git a/src/elements/emby-playstatebutton/emby-playstatebutton.js b/src/elements/emby-playstatebutton/emby-playstatebutton.js index 26a5c82807..610d732c90 100644 --- a/src/elements/emby-playstatebutton/emby-playstatebutton.js +++ b/src/elements/emby-playstatebutton/emby-playstatebutton.js @@ -1,6 +1,5 @@ -import connectionManager from 'jellyfin-apiclient'; import serverNotifications from '../../scripts/serverNotifications'; -import events from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import globalize from '../../scripts/globalize'; import EmbyButtonPrototype from '../../elements/emby-button/emby-button'; @@ -24,7 +23,7 @@ import EmbyButtonPrototype from '../../elements/emby-button/emby-button'; const button = this; const id = button.getAttribute('data-id'); const serverId = button.getAttribute('data-serverid'); - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); if (!button.classList.contains('playstatebutton-played')) { apiClient.markPlayed(apiClient.getCurrentUserId(), id, new Date()); diff --git a/src/elements/emby-ratingbutton/emby-ratingbutton.js b/src/elements/emby-ratingbutton/emby-ratingbutton.js index 42f7be68f7..15c290fa6f 100644 --- a/src/elements/emby-ratingbutton/emby-ratingbutton.js +++ b/src/elements/emby-ratingbutton/emby-ratingbutton.js @@ -1,6 +1,5 @@ -import connectionManager from 'jellyfin-apiclient'; import serverNotifications from '../../scripts/serverNotifications'; -import events from 'jellyfin-apiclient'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; import globalize from '../../scripts/globalize'; import EmbyButtonPrototype from '../emby-button/emby-button'; @@ -28,7 +27,7 @@ import EmbyButtonPrototype from '../emby-button/emby-button'; const button = this; const id = button.getAttribute('data-id'); const serverId = button.getAttribute('data-serverid'); - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); let likes = this.getAttribute('data-likes'); const isFavorite = this.getAttribute('data-isfavorite') === 'true'; diff --git a/src/elements/emby-tabs/emby-tabs.js b/src/elements/emby-tabs/emby-tabs.js index e34d30d47a..51144c7d3a 100644 --- a/src/elements/emby-tabs/emby-tabs.js +++ b/src/elements/emby-tabs/emby-tabs.js @@ -7,8 +7,6 @@ import './emby-tabs.css'; import '../../assets/css/scrollstyles.css'; /* eslint-disable indent */ - - const EmbyTabs = Object.create(HTMLDivElement.prototype); const buttonClass = 'emby-tab-button'; const activeButtonClass = buttonClass + '-active'; @@ -145,182 +143,181 @@ import '../../assets/css/scrollstyles.css'; } } - EmbyTabs.createdCallback = function () { - if (this.classList.contains('emby-tabs')) { - return; + class EmbyTabs extends HTMLDivElement { + createdCallback() { + if (this.classList.contains('emby-tabs')) { + return; + } + this.classList.add('emby-tabs'); + this.classList.add('focusable'); + + dom.addEventListener(this, 'click', onClick, { + passive: true + }); + + dom.addEventListener(this, 'focusout', onFocusOut); } - this.classList.add('emby-tabs'); - this.classList.add('focusable'); - dom.addEventListener(this, 'click', onClick, { - passive: true - }); + focus() { + const selected = this.querySelector('.' + activeButtonClass); - dom.addEventListener(this, 'focusout', onFocusOut); - }; - - EmbyTabs.focus = function onFocusIn() { - const selectedTab = this.querySelector('.' + activeButtonClass); - const lastFocused = this.querySelector('.lastFocused'); - - if (lastFocused) { - focusManager.focus(lastFocused); - } else if (selectedTab) { - focusManager.focus(selectedTab); - } else { - focusManager.autoFocus(this); - } - }; - - EmbyTabs.refresh = function () { - if (this.scroller) { - this.scroller.reload(); - } - }; - - EmbyTabs.attachedCallback = function () { - initScroller(this); - - const current = this.querySelector('.' + activeButtonClass); - const currentIndex = current ? parseInt(current.getAttribute('data-index')) : parseInt(this.getAttribute('data-index') || '0'); - - if (currentIndex !== -1) { - this.selectedTabIndex = currentIndex; - - const tabButtons = this.querySelectorAll('.' + buttonClass); - - const newTabButton = tabButtons[currentIndex]; - - if (newTabButton) { - setActiveTabButton(newTabButton); + if (this.lastFocused) { + focusManager.focus(this.lastFocused); + } else if (this.selectedTab) { + focusManager.focus(this.selectedTab); + } else { + focusManager.autoFocus(this); } } - if (!this.readyFired) { - this.readyFired = true; - this.dispatchEvent(new CustomEvent('ready', {})); - } - }; - - EmbyTabs.detachedCallback = function () { - if (this.scroller) { - this.scroller.destroy(); - this.scroller = null; + refresh() { + if (this.scroller) { + this.scroller.reload(); + } } - dom.removeEventListener(this, 'click', onClick, { - passive: true - }); - }; + attachedCallback() { + console.warn(this); + initScroller(this); - function getSelectedTabButton(elem) { - return elem.querySelector('.' + activeButtonClass); - } + const current = this.querySelector('.' + activeButtonClass); + const currentIndex = current ? parseInt(current.getAttribute('data-index')) : parseInt(this.getAttribute('data-index') || '0'); - EmbyTabs.selectedIndex = function (selected, triggerEvent) { - const tabs = this; + if (currentIndex !== -1) { + this.selectedTabIndex = currentIndex; - if (selected == null) { - return tabs.selectedTabIndex || 0; + const tabButtons = this.querySelectorAll('.' + buttonClass); + + const newTabButton = tabButtons[currentIndex]; + + if (newTabButton) { + setActiveTabButton(newTabButton); + } + } + + if (!this.readyFired) { + this.readyFired = true; + this.dispatchEvent(new CustomEvent('ready', {})); + } } - const current = tabs.selectedIndex(); + detachedCallback() { + if (this.scroller) { + this.scroller.destroy(); + this.scroller = null; + } - tabs.selectedTabIndex = selected; + dom.removeEventListener(this, 'click', onClick, { + passive: true + }); + } - const tabButtons = tabs.querySelectorAll('.' + buttonClass); + getSelectedTabButton(elem) { + return elem.querySelector('.' + activeButtonClass); + } - if (current === selected || triggerEvent === false) { - triggerBeforeTabChange(tabs, selected, current); + selectedIndex(selected, triggerEvent) { + const tabs = this; + + if (selected == null) { + return tabs.selectedTabIndex || 0; + } + + const current = tabs.selectedIndex(); + + tabs.selectedTabIndex = selected; + + const tabButtons = tabs.querySelectorAll('.' + buttonClass); + + if (current === selected || triggerEvent === false) { + triggerBeforeTabChange(tabs, selected, current); + + tabs.dispatchEvent(new CustomEvent('tabchange', { + detail: { + selectedTabIndex: selected + } + })); + + const currentTabButton = tabButtons[current]; + setActiveTabButton(tabButtons[selected]); + + if (current !== selected && currentTabButton) { + currentTabButton.classList.remove(activeButtonClass); + } + } else { + onClick.call(tabs, { + target: tabButtons[selected] + }); + } + } + + getSibling(elem, method) { + let sibling = elem[method]; + + while (sibling) { + if (sibling.classList.contains(buttonClass)) { + if (!sibling.classList.contains('hide')) { + return sibling; + } + } + + sibling = sibling[method]; + } + + return null; + } + + selectNext() { + const current = this.getSelectedTabButton(this); + + const sibling = this.getSibling(current, 'nextSibling'); + + if (sibling) { + onClick.call(this, { + target: sibling + }); + } + } + + selectPrevious() { + const current = this.getSelectedTabButton(this); + + const sibling = this.getSibling(current, 'previousSibling'); + + if (sibling) { + onClick.call(this, { + target: sibling + }); + } + } + + triggerBeforeTabChange(selected) { + const tabs = this; + + triggerBeforeTabChange(tabs, tabs.selectedIndex()); + } + + triggerTabChange(selected) { + const tabs = this; tabs.dispatchEvent(new CustomEvent('tabchange', { detail: { - selectedTabIndex: selected + selectedTabIndex: tabs.selectedIndex() } })); - - const currentTabButton = tabButtons[current]; - setActiveTabButton(tabButtons[selected]); - - if (current !== selected && currentTabButton) { - currentTabButton.classList.remove(activeButtonClass); - } - } else { - onClick.call(tabs, { - target: tabButtons[selected] - }); - } - }; - - function getSibling(elem, method) { - let sibling = elem[method]; - - while (sibling) { - if (sibling.classList.contains(buttonClass)) { - if (!sibling.classList.contains('hide')) { - return sibling; - } - } - - sibling = sibling[method]; } - return null; + setTabEnabled(index, enabled) { + const btn = this.querySelector('.emby-tab-button[data-index="' + index + '"]'); + + if (enabled) { + btn.classList.remove('hide'); + } else { + btn.classList.remove('add'); + } + } } - EmbyTabs.selectNext = function () { - const current = getSelectedTabButton(this); - - const sibling = getSibling(current, 'nextSibling'); - - if (sibling) { - onClick.call(this, { - target: sibling - }); - } - }; - - EmbyTabs.selectPrevious = function () { - const current = getSelectedTabButton(this); - - const sibling = getSibling(current, 'previousSibling'); - - if (sibling) { - onClick.call(this, { - target: sibling - }); - } - }; - - EmbyTabs.triggerBeforeTabChange = function (selected) { - const tabs = this; - - triggerBeforeTabChange(tabs, tabs.selectedIndex()); - }; - - EmbyTabs.triggerTabChange = function (selected) { - const tabs = this; - - tabs.dispatchEvent(new CustomEvent('tabchange', { - detail: { - selectedTabIndex: tabs.selectedIndex() - } - })); - }; - - EmbyTabs.setTabEnabled = function (index, enabled) { - const btn = this.querySelector('.emby-tab-button[data-index="' + index + '"]'); - - if (enabled) { - btn.classList.remove('hide'); - } else { - btn.classList.remove('add'); - } - }; - - document.registerElement('emby-tabs', { - prototype: EmbyTabs, - extends: 'div' - }); + customElements.define('emby-tabs', EmbyTabs, { extends: 'div' }); /* eslint-enable indent */ diff --git a/src/libraries/navdrawer/navdrawer.js b/src/libraries/navdrawer/navdrawer.js index 4af9f56a1c..214d86a02c 100644 --- a/src/libraries/navdrawer/navdrawer.js +++ b/src/libraries/navdrawer/navdrawer.js @@ -8,7 +8,7 @@ import dom from '../../scripts/dom'; import './navdrawer.css'; import '../../assets/css/scrollstyles.css'; -export default function (options) { +export function NavigationDrawer(options) { function getTouches(e) { return e.changedTouches || e.targetTouches || e.touches; } diff --git a/src/libraries/screensavermanager.js b/src/libraries/screensavermanager.js index 93625449f2..7d180fb7f6 100644 --- a/src/libraries/screensavermanager.js +++ b/src/libraries/screensavermanager.js @@ -1,8 +1,7 @@ -import events from 'jellyfin-apiclient'; -import playbackManager from '../components/playback/playbackmanager'; -import pluginManager from '../components/pluginManager'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; +import { playbackManager } from '../components/playback/playbackmanager'; +import { pluginManager } from '../components/pluginManager'; import inputManager from '../scripts/inputManager'; -import connectionManager from 'jellyfin-apiclient'; import * as userSettings from '../scripts/settings/userSettings'; function getMinIdleTime() { @@ -85,7 +84,7 @@ function ScreenSaverManager() { this.show = function () { let isLoggedIn; - const apiClient = window.connectionManager.currentApiClient(); + const apiClient = ConnectionManager.currentApiClient(); if (apiClient && apiClient.isLoggedIn()) { isLoggedIn = true; diff --git a/src/libraries/scroller.js b/src/libraries/scroller.js index f2baf51572..e6b7aeae0e 100644 --- a/src/libraries/scroller.js +++ b/src/libraries/scroller.js @@ -195,6 +195,7 @@ const scrollerFactory = function (frame, options) { self.frameResizeObserver = new ResizeObserver(onResize, observerOptions); + console.warn(frame); self.frameResizeObserver.observe(frame); } diff --git a/src/plugins/backdropScreensaver/plugin.js b/src/plugins/backdropScreensaver/plugin.js index 917d8f48a3..0def71878a 100644 --- a/src/plugins/backdropScreensaver/plugin.js +++ b/src/plugins/backdropScreensaver/plugin.js @@ -1,4 +1,5 @@ /* eslint-disable indent */ +import { ConnectionManager } from 'jellyfin-apiclient'; class BackdropScreensaver { constructor() { @@ -20,10 +21,10 @@ class BackdropScreensaver { Limit: 200 }; - const apiClient = window.connectionManager.currentApiClient(); + const apiClient = ConnectionManager.currentApiClient(); apiClient.getItems(apiClient.getCurrentUserId(), query).then((result) => { if (result.Items.length) { - import('slideshow').then(({default: Slideshow}) => { + import('../../components/slideshow/slideshow').then(({default: Slideshow}) => { const newSlideShow = new Slideshow({ showTitle: true, cover: true, diff --git a/src/plugins/bookPlayer/plugin.js b/src/plugins/bookPlayer/plugin.js index 60f12f2b5f..b513cfe60e 100644 --- a/src/plugins/bookPlayer/plugin.js +++ b/src/plugins/bookPlayer/plugin.js @@ -1,10 +1,9 @@ -import connectionManager from 'jellyfin-apiclient'; import loading from '../../components/loading/loading'; -import keyboardnavigation from 'keyboardnavigation'; -import dialogHelper from 'dialogHelper'; -import dom from 'dom'; -import events from 'jellyfin-apiclient'; -import './style'; +import keyboardnavigation from '../../scripts/keyboardNavigation'; +import dialogHelper from '../../components/dialogHelper/dialogHelper'; +import dom from '../../scripts/dom'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; +import './style.css'; import 'material-design-icons-iconfont'; import '../../elements/emby-button/paper-icon-button-light'; @@ -260,7 +259,7 @@ export class BookPlayer { }; const serverId = item.ServerId; - const apiClient = window.connectionManager.getApiClient(serverId); + const apiClient = ConnectionManager.getApiClient(serverId); return new Promise((resolve, reject) => { import('epubjs').then(({default: epubjs}) => { diff --git a/src/plugins/bookPlayer/tableOfContents.js b/src/plugins/bookPlayer/tableOfContents.js index 165c1fa9ac..db498c10fd 100644 --- a/src/plugins/bookPlayer/tableOfContents.js +++ b/src/plugins/bookPlayer/tableOfContents.js @@ -1,4 +1,4 @@ -import dialogHelper from 'dialogHelper'; +import dialogHelper from '../../components/dialogHelper/dialogHelper'; export default class TableOfContents { constructor(bookPlayer) { diff --git a/src/plugins/chromecastPlayer/plugin.js b/src/plugins/chromecastPlayer/plugin.js index ba09f9e209..ad8ecc0b9a 100644 --- a/src/plugins/chromecastPlayer/plugin.js +++ b/src/plugins/chromecastPlayer/plugin.js @@ -1,9 +1,9 @@ -import appSettings from 'appSettings'; +import appSettings from '../../scripts/settings/appSettings'; import * as userSettings from '../../scripts/settings/userSettings'; -import playbackManager from 'playbackManager'; -import globalize from 'globalize'; -import events from 'jellyfin-apiclient'; -import castSenderApiLoader from 'castSenderApiLoader'; +import { playbackManager } from '../../components/playback/playbackmanager'; +import globalize from '../../scripts/globalize'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; +import castSenderApiLoader from '../../components/castSenderApi'; // Based on https://github.com/googlecast/CastVideos-chrome/blob/master/CastVideos.js @@ -324,11 +324,11 @@ class CastPlayer { let apiClient; if (message.options && message.options.ServerId) { - apiClient = window.connectionManager.getApiClient(message.options.ServerId); + apiClient = ConnectionManager.getApiClient(message.options.ServerId); } else if (message.options && message.options.items && message.options.items.length) { - apiClient = window.connectionManager.getApiClient(message.options.items[0].ServerId); + apiClient = ConnectionManager.getApiClient(message.options.items[0].ServerId); } else { - apiClient = window.connectionManager.currentApiClient(); + apiClient = ConnectionManager.currentApiClient(); } message = Object.assign(message, { @@ -439,7 +439,7 @@ class CastPlayer { } function alertText(text, title) { - import('alert').then(({default: alert}) => { + import('../../components/alert').then(({default: alert}) => { alert({ text: text, title: title @@ -672,7 +672,7 @@ class ChromecastPlayer { playWithCommand(options, command) { if (!options.items) { - const apiClient = window.connectionManager.getApiClient(options.serverId); + const apiClient = ConnectionManager.getApiClient(options.serverId); const instance = this; return apiClient.getItem(apiClient.getCurrentUserId(), options.ids[0]).then(function (item) { @@ -984,7 +984,7 @@ class ChromecastPlayer { } shuffle(item) { - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); const userId = apiClient.getCurrentUserId(); const instance = this; @@ -997,7 +997,7 @@ class ChromecastPlayer { } instantMix(item) { - const apiClient = window.connectionManager.getApiClient(item.ServerId); + const apiClient = ConnectionManager.getApiClient(item.ServerId); const userId = apiClient.getCurrentUserId(); const instance = this; @@ -1035,7 +1035,7 @@ class ChromecastPlayer { } const instance = this; - const apiClient = window.connectionManager.getApiClient(options.serverId); + const apiClient = ConnectionManager.getApiClient(options.serverId); return getItemsForPlayback(apiClient, { Ids: options.ids.join(',') diff --git a/src/plugins/experimentalWarnings/plugin.js b/src/plugins/experimentalWarnings/plugin.js index bc301f01af..fb9957aea4 100644 --- a/src/plugins/experimentalWarnings/plugin.js +++ b/src/plugins/experimentalWarnings/plugin.js @@ -1,6 +1,6 @@ -import globalize from 'globalize'; -import * as userSettings from 'userSettings'; -import appHost from 'apphost'; +import globalize from '../../scripts/globalize'; +import * as userSettings from '../../scripts/settings/userSettings'; +import { appHost } from '../../components/apphost'; // TODO: Replace with date-fns // https://stackoverflow.com/questions/6117814/get-week-of-year-in-javascript-like-in-php @@ -29,7 +29,7 @@ function showMessage(text, userSettingsKey, appHostFeature) { return new Promise(function (resolve, reject) { userSettings.set(userSettingsKey, '1', false); - import('alert').then(({default: alert}) => { + import('../../components/alert').then(({default: alert}) => { return alert(text).then(resolve, resolve); }); }); diff --git a/src/plugins/htmlAudioPlayer/plugin.js b/src/plugins/htmlAudioPlayer/plugin.js index 68380bcdb4..342a8a208a 100644 --- a/src/plugins/htmlAudioPlayer/plugin.js +++ b/src/plugins/htmlAudioPlayer/plugin.js @@ -1,10 +1,10 @@ -import events from 'jellyfin-apiclient'; -import browser from 'browser'; -import appHost from 'apphost'; -import * as htmlMediaHelper from 'htmlMediaHelper'; +import { events } from 'jellyfin-apiclient'; +import browser from '../../scripts/browser'; +import { appHost } from '../../components/apphost'; +import * as htmlMediaHelper from '../../components/htmlMediaHelper'; function getDefaultProfile() { - return import('browserdeviceprofile').then(({ default: profileBuilder }) => { + return import('../../scripts/browserDeviceProfile').then(({ default: profileBuilder }) => { return profileBuilder({}); }); } @@ -51,7 +51,7 @@ function supportsFade() { } function requireHlsPlayer(callback) { - import('hlsjs').then(({ default: hls }) => { + import('hls.js').then(({ default: hls }) => { window.Hls = hls; callback(); }); @@ -68,7 +68,7 @@ function enableHlsPlayer(url, item, mediaSource, mediaType) { // issue head request to get content type return new Promise(function (resolve, reject) { - import('fetchHelper').then((fetchHelper) => { + import('../../components/fetchhelper').then((fetchHelper) => { fetchHelper.ajax({ url: url, type: 'HEAD' diff --git a/src/plugins/htmlVideoPlayer/plugin.js b/src/plugins/htmlVideoPlayer/plugin.js index f4c7f25b70..2c5072a073 100644 --- a/src/plugins/htmlVideoPlayer/plugin.js +++ b/src/plugins/htmlVideoPlayer/plugin.js @@ -1,10 +1,10 @@ -import browser from 'browser'; -import events from 'jellyfin-apiclient'; -import appHost from 'apphost'; +import browser from '../../scripts/browser'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; +import { appHost } from '../../components/apphost'; import loading from '../../components/loading/loading'; -import dom from 'dom'; -import playbackManager from 'playbackManager'; -import appRouter from 'appRouter'; +import dom from '../../scripts/dom'; +import { playbackManager } from '../../components/playback/playbackmanager'; +import { appRouter } from '../../components/appRouter'; import { bindEventsToHlsPlayer, destroyHlsPlayer, @@ -22,10 +22,10 @@ import { getSavedVolume, isValidDuration, getBufferedRanges -} from 'htmlMediaHelper'; -import itemHelper from 'itemHelper'; -import screenfull from 'screenfull'; -import globalize from 'globalize'; +} from '../../components/htmlMediaHelper'; +import itemHelper from '../../components/itemHelper'; +import Screenfull from 'screenfull'; +import globalize from '../../scripts/globalize'; /* eslint-disable indent */ @@ -85,7 +85,7 @@ function tryRemoveElement(elem) { } function requireHlsPlayer(callback) { - import('hlsjs').then(({default: hls}) => { + import('hls.js').then(({default: hls}) => { window.Hls = hls; callback(); }); @@ -139,7 +139,7 @@ function tryRemoveElement(elem) { } function getDefaultProfile() { - return import('browserdeviceprofile').then(({default: profileBuilder}) => { + return import('../../scripts/browserDeviceProfile').then(({default: profileBuilder}) => { return profileBuilder({}); }); } @@ -323,7 +323,7 @@ function tryRemoveElement(elem) { console.debug(`prefetching hls playlist: ${hlsPlaylistUrl}`); - return window.connectionManager.getApiClient(item.ServerId).ajax({ + return ConnectionManager.getApiClient(item.ServerId).ajax({ type: 'GET', url: hlsPlaylistUrl @@ -362,7 +362,7 @@ function tryRemoveElement(elem) { * @private */ setSrcWithFlvJs(elem, options, url) { - return import('flvjs').then(({default: flvjs}) => { + return import('flv.js').then(({default: flvjs}) => { const flvPlayer = flvjs.createPlayer({ type: 'flv', url: url @@ -704,8 +704,8 @@ function tryRemoveElement(elem) { dlg.parentNode.removeChild(dlg); } - if (screenfull.isEnabled) { - screenfull.exit(); + if (Screenfull.isEnabled) { + Screenfull.exit(); } else { // iOS Safari if (document.webkitIsFullScreen && document.webkitCancelFullscreen) { @@ -1031,7 +1031,7 @@ function tryRemoveElement(elem) { */ renderSsaAss(videoElement, track, item) { const attachments = this._currentPlayOptions.mediaSource.MediaAttachments || []; - const apiClient = window.connectionManager.getApiClient(item); + const apiClient = ConnectionManager.getApiClient(item); const htmlVideoPlayer = this; const options = { video: videoElement, @@ -1058,7 +1058,7 @@ function tryRemoveElement(elem) { resizeVariation: 0.2, renderAhead: 90 }; - import('JavascriptSubtitlesOctopus').then(({default: SubtitlesOctopus}) => { + import('libass-wasm').then(({default: SubtitlesOctopus}) => { this.#currentSubtitlesOctopus = new SubtitlesOctopus(options); }); } @@ -1114,7 +1114,7 @@ function tryRemoveElement(elem) { * @private */ setSubtitleAppearance(elem, innerElem) { - Promise.all([import('userSettings'), import('subtitleAppearanceHelper')]).then(([userSettings, subtitleAppearanceHelper]) => { + Promise.all([import('../../scripts/settings/userSettings'), import('../../components/subtitlesettings/subtitleappearancehelper')]).then(([userSettings, subtitleAppearanceHelper]) => { subtitleAppearanceHelper.applyStyles({ text: innerElem, window: elem @@ -1135,7 +1135,7 @@ function tryRemoveElement(elem) { * @private */ setCueAppearance() { - Promise.all([import('userSettings'), import('subtitleAppearanceHelper')]).then(([userSettings, subtitleAppearanceHelper]) => { + Promise.all([import('../../scripts/settings/userSettings'), import('../../components/subtitlesettings/subtitleappearancehelper')]).then(([userSettings, subtitleAppearanceHelper]) => { const elementId = `${this.id}-cuestyle`; let styleElem = document.querySelector(`#${elementId}`); @@ -1190,7 +1190,7 @@ function tryRemoveElement(elem) { // download the track json this.fetchSubtitles(track, item).then(function (data) { - import('userSettings').then((userSettings) => { + import('../../scripts/settings/userSettings').then((userSettings) => { // show in ui console.debug(`downloaded ${data.TrackEvents.length} track events`); @@ -1282,7 +1282,7 @@ function tryRemoveElement(elem) { const dlg = document.querySelector('.videoPlayerContainer'); if (!dlg) { - return import('./style').then(() => { + return import('./style.css').then(() => { loading.show(); const dlg = document.createElement('div'); diff --git a/src/plugins/logoScreensaver/plugin.js b/src/plugins/logoScreensaver/plugin.js index 619c0de253..7c2b71342c 100644 --- a/src/plugins/logoScreensaver/plugin.js +++ b/src/plugins/logoScreensaver/plugin.js @@ -1,5 +1,3 @@ -import pluginManager from 'pluginManager'; - export default function () { const self = this; @@ -128,7 +126,7 @@ export default function () { } self.show = function () { - import('' + pluginManager.mapPath(self, 'style.css')).then(() => { + import('./style.css').then(() => { let elem = document.querySelector('.logoScreenSaver'); if (!elem) { diff --git a/src/plugins/photoPlayer/plugin.js b/src/plugins/photoPlayer/plugin.js index c40477778e..9ea48a11af 100644 --- a/src/plugins/photoPlayer/plugin.js +++ b/src/plugins/photoPlayer/plugin.js @@ -1,3 +1,4 @@ +import { ConnectionManager } from 'jellyfin-apiclient'; export default class PhotoPlayer { constructor() { @@ -9,12 +10,12 @@ export default class PhotoPlayer { play(options) { return new Promise(function (resolve, reject) { - import('slideshow').then(({default: slideshow}) => { - const index = options.startIndex || 0; + import('../../components/slideshow/slideshow').then(({default: Slideshow}) => { + var index = options.startIndex || 0; - const apiClient = window.connectionManager.currentApiClient(); + var apiClient = ConnectionManager.currentApiClient(); apiClient.getCurrentUser().then(function(result) { - const newSlideShow = new slideshow({ + var newSlideShow = new Slideshow({ showTitle: false, cover: false, items: options.items, diff --git a/src/plugins/playAccessValidation/plugin.js b/src/plugins/playAccessValidation/plugin.js index c64b63332b..65f6732c25 100644 --- a/src/plugins/playAccessValidation/plugin.js +++ b/src/plugins/playAccessValidation/plugin.js @@ -1,7 +1,8 @@ -import globalize from 'globalize'; +import { ConnectionManager } from 'jellyfin-apiclient'; +import globalize from '../../scripts/globalize'; function showErrorMessage() { - return import('alert').then(({default: alert}) => { + return import('../../components/alert').then(({default: alert}) => { return alert(globalize.translate('MessagePlayAccessRestricted')); }); } @@ -24,7 +25,7 @@ class PlayAccessValidation { return Promise.resolve(); } - return window.connectionManager.getApiClient(serverId).getCurrentUser().then(function (user) { + return ConnectionManager.getApiClient(serverId).getCurrentUser().then(function (user) { if (user.Policy.EnableMediaPlayback) { return Promise.resolve(); } diff --git a/src/plugins/sessionPlayer/plugin.js b/src/plugins/sessionPlayer/plugin.js index 619266b01f..bbf13ffb4b 100644 --- a/src/plugins/sessionPlayer/plugin.js +++ b/src/plugins/sessionPlayer/plugin.js @@ -1,6 +1,6 @@ -import playbackManager from 'playbackManager'; -import events from 'events'; -import serverNotifications from 'serverNotifications'; +import { playbackManager } from '../../components/playback/playbackmanager'; +import { ConnectionManager, events } from 'jellyfin-apiclient'; +import serverNotifications from '../../scripts/serverNotifications'; function getActivePlayerId() { const info = playbackManager.getPlayerInfo(); @@ -53,10 +53,10 @@ function getCurrentApiClient(instance) { const currentServerId = instance.currentServerId; if (currentServerId) { - return window.connectionManager.getApiClient(currentServerId); + return ConnectionManager.getApiClient(currentServerId); } - return window.connectionManager.currentApiClient(); + return ConnectionManager.currentApiClient(); } function sendCommandByName(instance, name, options) { diff --git a/src/plugins/youtubePlayer/plugin.js b/src/plugins/youtubePlayer/plugin.js index 568077b0f9..a975d8e34c 100644 --- a/src/plugins/youtubePlayer/plugin.js +++ b/src/plugins/youtubePlayer/plugin.js @@ -1,6 +1,6 @@ -import events from 'jellyfin-apiclient'; -import browser from 'browser'; -import appRouter from 'appRouter'; +import { events } from 'jellyfin-apiclient'; +import browser from '../../scripts/browser'; +import { appRouter } from '../../components/appRouter'; import loading from '../../components/loading/loading'; /* globals YT */ @@ -20,7 +20,7 @@ function createMediaElement(instance, options) { const dlg = document.querySelector('.youtubePlayerContainer'); if (!dlg) { - import('./style').then(() => { + import('./style.css').then(() => { loading.show(); const dlg = document.createElement('div'); @@ -114,7 +114,7 @@ function onPlaying(instance, playOptions, resolve) { instance.videoDialog.classList.remove('onTop'); } - import('loading').then(({default: loading}) => { + import('../../components/loading/loading').then(({default: loading}) => { loading.hide(); }); } @@ -122,60 +122,58 @@ function onPlaying(instance, playOptions, resolve) { function setCurrentSrc(instance, elem, options) { return new Promise(function (resolve, reject) { - import('queryString').then(({default: queryString}) => { - instance._currentSrc = options.url; - const params = queryString.parse(options.url.split('?')[1]); - // 3. This function creates an