From ab52727254019450db9a9fab25bc5eb4cddc504a Mon Sep 17 00:00:00 2001 From: matjaz321 Date: Sat, 1 Aug 2020 15:32:57 +0200 Subject: [PATCH 01/56] Migrated livetvseriestimer to es6 module --- src/controllers/livetv/livetvseriestimers.js | 90 ++++++++++---------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/src/controllers/livetv/livetvseriestimers.js b/src/controllers/livetv/livetvseriestimers.js index c5d0da60d7..d645a66370 100644 --- a/src/controllers/livetv/livetvseriestimers.js +++ b/src/controllers/livetv/livetvseriestimers.js @@ -1,50 +1,52 @@ -define(['datetime', 'cardBuilder', 'imageLoader', 'apphost', 'loading', 'paper-icon-button-light', 'emby-button'], function (datetime, cardBuilder, imageLoader, appHost, loading) { - 'use strict'; +import cardBuilder from 'cardBuilder'; +import imageLoader from 'imageLoader'; +import loading from 'loading'; +import 'paper-icon-button-light'; +import 'emby-button'; - function renderTimers(context, timers) { - var html = ''; - html += cardBuilder.getCardsHtml({ - items: timers, - shape: 'auto', - defaultShape: 'portrait', - showTitle: true, - cardLayout: false, - preferThumb: 'auto', - coverImage: true, - overlayText: false, - showSeriesTimerTime: true, - showSeriesTimerChannel: true, - centerText: true, - overlayMoreButton: true, - lines: 3 - }); - var elem = context.querySelector('#items'); - elem.innerHTML = html; - imageLoader.lazyChildren(elem); - loading.hide(); - } +function renderTimers(context, timers) { + const html = cardBuilder.getCardsHtml({ + items: timers, + shape: 'auto', + defaultShape: 'portrait', + showTitle: true, + cardLayout: false, + preferThumb: 'auto', + coverImage: true, + overlayText: false, + showSeriesTimerTime: true, + showSeriesTimerChannel: true, + centerText: true, + overlayMoreButton: true, + lines: 3 + }); + const elem = context.querySelector('#items'); + elem.innerHTML = html; + imageLoader.lazyChildren(elem); + loading.hide(); +} - function reload(context, promise) { - loading.show(); - promise.then(function (result) { - renderTimers(context, result.Items); - }); - } +function reload(context, promise) { + loading.show(); + promise.then(function (result) { + renderTimers(context, result.Items); + }); +} - var query = { - SortBy: 'SortName', - SortOrder: 'Ascending' +const query = { + SortBy: 'SortName', + SortOrder: 'Ascending' +}; + +export default function (view, params, tabContent) { + let timersPromise; + const self = this; + + self.preRender = function () { + timersPromise = ApiClient.getLiveTvSeriesTimers(query); }; - return function (view, params, tabContent) { - var timersPromise; - var self = this; - self.preRender = function () { - timersPromise = ApiClient.getLiveTvSeriesTimers(query); - }; - - self.renderTab = function () { - reload(tabContent, timersPromise); - }; + self.renderTab = function () { + reload(tabContent, timersPromise); }; -}); +}; From 0c8e1994b79eebee5056c03bc1056b3d658c94ca Mon Sep 17 00:00:00 2001 From: matjaz321 Date: Sat, 1 Aug 2020 15:36:16 +0200 Subject: [PATCH 02/56] fixed linting errors --- src/controllers/livetv/livetvseriestimers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/livetv/livetvseriestimers.js b/src/controllers/livetv/livetvseriestimers.js index d645a66370..4f6bfaaa6a 100644 --- a/src/controllers/livetv/livetvseriestimers.js +++ b/src/controllers/livetv/livetvseriestimers.js @@ -49,4 +49,4 @@ export default function (view, params, tabContent) { self.renderTab = function () { reload(tabContent, timersPromise); }; -}; +} From a7ad147aad2dda101ec26aa7e44d8a1008448bee Mon Sep 17 00:00:00 2001 From: Cameron Date: Sun, 2 Aug 2020 18:48:57 +0100 Subject: [PATCH 03/56] Migration of xmltv and livetvguideprovide to ES6 module --- package.json | 2 + src/components/tvproviders/schedulesdirect.js | 543 +++++++++--------- src/components/tvproviders/xmltv.js | 356 ++++++------ src/controllers/livetvguideprovider.js | 2 +- 4 files changed, 456 insertions(+), 447 deletions(-) diff --git a/package.json b/package.json index 22fd43308a..43d806b8de 100644 --- a/package.json +++ b/package.json @@ -166,6 +166,8 @@ "src/components/syncPlay/playbackPermissionManager.js", "src/components/syncPlay/syncPlayManager.js", "src/components/syncPlay/timeSyncManager.js", + "src/components/tvproviders/schedulesdirect.js", + "src/components/tvproviders/xmltv.js", "src/components/viewContainer.js", "src/controllers/session/addServer/index.js", "src/controllers/session/forgotPassword/index.js", diff --git a/src/components/tvproviders/schedulesdirect.js b/src/components/tvproviders/schedulesdirect.js index a0c29f48b8..9d60310e98 100644 --- a/src/components/tvproviders/schedulesdirect.js +++ b/src/components/tvproviders/schedulesdirect.js @@ -1,299 +1,304 @@ -define(['jQuery', 'loading', 'globalize', 'emby-checkbox', 'listViewStyle', 'emby-input', 'emby-select', 'emby-button', 'flexStyles'], function ($, loading, globalize) { - 'use strict'; +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'; - loading = loading.default || loading; +export default function (page, providerId, options) { + function reload() { + loading.show(); + ApiClient.getNamedConfiguration('livetv').then(function (config) { + var info = config.ListingProviders.filter(function (i) { + return i.Id === providerId; + })[0] || {}; + listingsId = info.ListingsId; + $('#selectListing', page).val(info.ListingsId || ''); + page.querySelector('.txtUser').value = info.Username || ''; + page.querySelector('.txtPass').value = ''; + page.querySelector('.txtZipCode').value = info.ZipCode || ''; - return function (page, providerId, options) { - function reload() { - loading.show(); - ApiClient.getNamedConfiguration('livetv').then(function (config) { - var info = config.ListingProviders.filter(function (i) { - return i.Id === providerId; - })[0] || {}; - listingsId = info.ListingsId; - $('#selectListing', page).val(info.ListingsId || ''); - page.querySelector('.txtUser').value = info.Username || ''; - page.querySelector('.txtPass').value = ''; - page.querySelector('.txtZipCode').value = info.ZipCode || ''; - - if (info.Username && info.Password) { - page.querySelector('.listingsSection').classList.remove('hide'); - } else { - page.querySelector('.listingsSection').classList.add('hide'); - } - - page.querySelector('.chkAllTuners').checked = info.EnableAllTuners; - - if (info.EnableAllTuners) { - page.querySelector('.selectTunersSection').classList.add('hide'); - } else { - page.querySelector('.selectTunersSection').classList.remove('hide'); - } - - setCountry(info); - refreshTunerDevices(page, info, config.TunerHosts); - }); - } - - function setCountry(info) { - ApiClient.getJSON(ApiClient.getUrl('LiveTv/ListingProviders/SchedulesDirect/Countries')).then(function (result) { - var i; - var length; - var countryList = []; - - for (var region in result) { - var countries = result[region]; - - if (countries.length && region !== 'ZZZ') { - for (i = 0, length = countries.length; i < length; i++) { - countryList.push({ - name: countries[i].fullName, - value: countries[i].shortName - }); - } - } - } - - countryList.sort(function (a, b) { - if (a.name > b.name) { - return 1; - } - - if (a.name < b.name) { - return -1; - } - - return 0; - }); - $('#selectCountry', page).html(countryList.map(function (c) { - return ''; - }).join('')).val(info.Country || ''); - $(page.querySelector('.txtZipCode')).trigger('change'); - }, function () { // ApiClient.getJSON() error handler - Dashboard.alert({ - message: globalize.translate('ErrorGettingTvLineups') - }); - }); - loading.hide(); - } - - function sha256(str) { - if (!self.TextEncoder) { - return Promise.resolve(''); + if (info.Username && info.Password) { + page.querySelector('.listingsSection').classList.remove('hide'); + } else { + page.querySelector('.listingsSection').classList.add('hide'); } - var buffer = new TextEncoder('utf-8').encode(str); - return crypto.subtle.digest('SHA-256', buffer).then(function (hash) { - return hex(hash); - }); - } + page.querySelector('.chkAllTuners').checked = info.EnableAllTuners; - function hex(buffer) { - var hexCodes = []; - var view = new DataView(buffer); - - for (var i = 0; i < view.byteLength; i += 4) { - var value = view.getUint32(i); - var stringValue = value.toString(16); - var paddedValue = ('00000000' + stringValue).slice(-'00000000'.length); - hexCodes.push(paddedValue); + if (info.EnableAllTuners) { + page.querySelector('.selectTunersSection').classList.add('hide'); + } else { + page.querySelector('.selectTunersSection').classList.remove('hide'); } - return hexCodes.join(''); - } + setCountry(info); + refreshTunerDevices(page, info, config.TunerHosts); + }); + } - function submitLoginForm() { - loading.show(); - sha256(page.querySelector('.txtPass').value).then(function (passwordHash) { - var info = { - Type: 'SchedulesDirect', - Username: page.querySelector('.txtUser').value, - EnableAllTuners: true, - Password: passwordHash, - Pw: page.querySelector('.txtPass').value - }; - var id = providerId; + function setCountry(info) { + ApiClient.getJSON(ApiClient.getUrl('LiveTv/ListingProviders/SchedulesDirect/Countries')).then(function (result) { + var i; + var length; + var countryList = []; - if (id) { - info.Id = id; + for (var region in result) { + var countries = result[region]; + + if (countries.length && region !== 'ZZZ') { + for (i = 0, length = countries.length; i < length; i++) { + countryList.push({ + name: countries[i].fullName, + value: countries[i].shortName + }); + } + } + } + + countryList.sort(function (a, b) { + if (a.name > b.name) { + return 1; } - ApiClient.ajax({ - type: 'POST', - url: ApiClient.getUrl('LiveTv/ListingProviders', { - ValidateLogin: true - }), - data: JSON.stringify(info), - contentType: 'application/json', - dataType: 'json' - }).then(function (result) { - Dashboard.processServerConfigurationUpdateResult(); - providerId = result.Id; - reload(); - }, function () { - Dashboard.alert({ // ApiClient.ajax() error handler - message: globalize.translate('ErrorSavingTvProvider') - }); - }); + if (a.name < b.name) { + return -1; + } + + return 0; }); + $('#selectCountry', page).html(countryList.map(function (c) { + return ''; + }).join('')).val(info.Country || ''); + $(page.querySelector('.txtZipCode')).trigger('change'); + }, function () { // ApiClient.getJSON() error handler + Dashboard.alert({ + message: globalize.translate('ErrorGettingTvLineups') + }); + }); + loading.hide(); + } + + function sha256(str) { + if (!self.TextEncoder) { + return Promise.resolve(''); } - function submitListingsForm() { - var selectedListingsId = $('#selectListing', page).val(); + var buffer = new TextEncoder('utf-8').encode(str); + return crypto.subtle.digest('SHA-256', buffer).then(function (hash) { + return hex(hash); + }); + } - if (!selectedListingsId) { - return void Dashboard.alert({ - message: globalize.translate('ErrorPleaseSelectLineup') - }); - } + function hex(buffer) { + var hexCodes = []; + var view = new DataView(buffer); - loading.show(); + for (var i = 0; i < view.byteLength; i += 4) { + var value = view.getUint32(i); + var stringValue = value.toString(16); + var paddedValue = ('00000000' + stringValue).slice(-'00000000'.length); + hexCodes.push(paddedValue); + } + + return hexCodes.join(''); + } + + function submitLoginForm() { + loading.show(); + sha256(page.querySelector('.txtPass').value).then(function (passwordHash) { + var info = { + Type: 'SchedulesDirect', + Username: page.querySelector('.txtUser').value, + EnableAllTuners: true, + Password: passwordHash, + Pw: page.querySelector('.txtPass').value + }; var id = providerId; - ApiClient.getNamedConfiguration('livetv').then(function (config) { - var info = config.ListingProviders.filter(function (i) { - return i.Id === id; - })[0]; - info.ZipCode = page.querySelector('.txtZipCode').value; - info.Country = $('#selectCountry', page).val(); - info.ListingsId = selectedListingsId; - info.EnableAllTuners = page.querySelector('.chkAllTuners').checked; - info.EnabledTuners = info.EnableAllTuners ? [] : $('.chkTuner', page).get().filter(function (i) { - return i.checked; - }).map(function (i) { - return i.getAttribute('data-id'); - }); - ApiClient.ajax({ - type: 'POST', - url: ApiClient.getUrl('LiveTv/ListingProviders', { - ValidateListings: true - }), - data: JSON.stringify(info), - contentType: 'application/json' - }).then(function (result) { - loading.hide(); - if (options.showConfirmation) { - Dashboard.processServerConfigurationUpdateResult(); - } - - Events.trigger(self, 'submitted'); - }, function () { - loading.hide(); - Dashboard.alert({ - message: globalize.translate('ErrorAddingListingsToSchedulesDirect') - }); - }); - }); - } - - function refreshListings(value) { - if (!value) { - return void $('#selectListing', page).html(''); + if (id) { + info.Id = id; } - loading.show(); ApiClient.ajax({ - type: 'GET', - url: ApiClient.getUrl('LiveTv/ListingProviders/Lineups', { - Id: providerId, - Location: value, - Country: $('#selectCountry', page).val() + type: 'POST', + url: ApiClient.getUrl('LiveTv/ListingProviders', { + ValidateLogin: true }), + data: JSON.stringify(info), + contentType: 'application/json', dataType: 'json' }).then(function (result) { - $('#selectListing', page).html(result.map(function (o) { - return ''; - })); - - if (listingsId) { - $('#selectListing', page).val(listingsId); - } - - loading.hide(); - }, function (result) { - Dashboard.alert({ - message: globalize.translate('ErrorGettingTvLineups') + Dashboard.processServerConfigurationUpdateResult(); + providerId = result.Id; + reload(); + }, function () { + Dashboard.alert({ // ApiClient.ajax() error handler + message: globalize.translate('ErrorSavingTvProvider') }); - refreshListings(''); + }); + }); + } + + function submitListingsForm() { + var selectedListingsId = $('#selectListing', page).val(); + + if (!selectedListingsId) { + return void Dashboard.alert({ + message: globalize.translate('ErrorPleaseSelectLineup') + }); + } + + loading.show(); + var id = providerId; + ApiClient.getNamedConfiguration('livetv').then(function (config) { + var info = config.ListingProviders.filter(function (i) { + return i.Id === id; + })[0]; + info.ZipCode = page.querySelector('.txtZipCode').value; + info.Country = $('#selectCountry', page).val(); + info.ListingsId = selectedListingsId; + info.EnableAllTuners = page.querySelector('.chkAllTuners').checked; + info.EnabledTuners = info.EnableAllTuners ? [] : $('.chkTuner', page).get().filter(function (i) { + return i.checked; + }).map(function (i) { + return i.getAttribute('data-id'); + }); + ApiClient.ajax({ + type: 'POST', + url: ApiClient.getUrl('LiveTv/ListingProviders', { + ValidateListings: true + }), + data: JSON.stringify(info), + contentType: 'application/json' + }).then(function (result) { loading.hide(); - }); - } - function getTunerName(providerId) { - switch (providerId = providerId.toLowerCase()) { - case 'm3u': - return 'M3U Playlist'; - case 'hdhomerun': - return 'HDHomerun'; - case 'satip': - return 'DVB'; - default: - return 'Unknown'; - } - } - - function refreshTunerDevices(page, providerInfo, devices) { - var html = ''; - - for (var i = 0, length = devices.length; i < length; i++) { - var device = devices[i]; - html += '
'; - var enabledTuners = providerInfo.EnabledTuners || []; - var isChecked = providerInfo.EnableAllTuners || enabledTuners.indexOf(device.Id) !== -1; - var checkedAttribute = isChecked ? ' checked' : ''; - html += ''; - html += '
'; - html += '
'; - html += device.FriendlyName || getTunerName(device.Type); - html += '
'; - html += '
'; - html += device.Url; - html += '
'; - html += '
'; - html += '
'; - } - - page.querySelector('.tunerList').innerHTML = html; - } - - var listingsId; - var self = this; - - self.submit = function () { - page.querySelector('.btnSubmitListingsContainer').click(); - }; - - self.init = function () { - options = options || {}; - - // Only hide the buttons if explicitly set to false; default to showing if undefined or null - // FIXME: rename this option to clarify logic - var hideCancelButton = options.showCancelButton === false; - page.querySelector('.btnCancel').classList.toggle('hide', hideCancelButton); - - var hideSubmitButton = options.showSubmitButton === false; - page.querySelector('.btnSubmitListings').classList.toggle('hide', hideSubmitButton); - - $('.formLogin', page).on('submit', function () { - submitLoginForm(); - return false; - }); - $('.formListings', page).on('submit', function () { - submitListingsForm(); - return false; - }); - $('.txtZipCode', page).on('change', function () { - refreshListings(this.value); - }); - page.querySelector('.chkAllTuners').addEventListener('change', function (e) { - if (e.target.checked) { - page.querySelector('.selectTunersSection').classList.add('hide'); - } else { - page.querySelector('.selectTunersSection').classList.remove('hide'); + if (options.showConfirmation) { + Dashboard.processServerConfigurationUpdateResult(); } + + Events.trigger(self, 'submitted'); + }, function () { + loading.hide(); + Dashboard.alert({ + message: globalize.translate('ErrorAddingListingsToSchedulesDirect') + }); }); - $('.createAccountHelp', page).html(globalize.translate('MessageCreateAccountAt', 'http://www.schedulesdirect.org')); - reload(); - }; + }); + } + + function refreshListings(value) { + if (!value) { + return void $('#selectListing', page).html(''); + } + + loading.show(); + ApiClient.ajax({ + type: 'GET', + url: ApiClient.getUrl('LiveTv/ListingProviders/Lineups', { + Id: providerId, + Location: value, + Country: $('#selectCountry', page).val() + }), + dataType: 'json' + }).then(function (result) { + $('#selectListing', page).html(result.map(function (o) { + return ''; + })); + + if (listingsId) { + $('#selectListing', page).val(listingsId); + } + + loading.hide(); + }, function (result) { + Dashboard.alert({ + message: globalize.translate('ErrorGettingTvLineups') + }); + refreshListings(''); + loading.hide(); + }); + } + + function getTunerName(providerId) { + switch (providerId = providerId.toLowerCase()) { + case 'm3u': + return 'M3U Playlist'; + case 'hdhomerun': + return 'HDHomerun'; + case 'satip': + return 'DVB'; + default: + return 'Unknown'; + } + } + + function refreshTunerDevices(page, providerInfo, devices) { + var html = ''; + + for (var i = 0, length = devices.length; i < length; i++) { + var device = devices[i]; + html += '
'; + var enabledTuners = providerInfo.EnabledTuners || []; + var isChecked = providerInfo.EnableAllTuners || enabledTuners.indexOf(device.Id) !== -1; + var checkedAttribute = isChecked ? ' checked' : ''; + html += ''; + html += '
'; + html += '
'; + html += device.FriendlyName || getTunerName(device.Type); + html += '
'; + html += '
'; + html += device.Url; + html += '
'; + html += '
'; + html += '
'; + } + + page.querySelector('.tunerList').innerHTML = html; + } + + var listingsId; + var self = this; + + self.submit = function () { + page.querySelector('.btnSubmitListingsContainer').click(); }; -}); + + self.init = function () { + options = options || {}; + + // Only hide the buttons if explicitly set to false; default to showing if undefined or null + // FIXME: rename this option to clarify logic + var hideCancelButton = options.showCancelButton === false; + page.querySelector('.btnCancel').classList.toggle('hide', hideCancelButton); + + var hideSubmitButton = options.showSubmitButton === false; + page.querySelector('.btnSubmitListings').classList.toggle('hide', hideSubmitButton); + + $('.formLogin', page).on('submit', function () { + submitLoginForm(); + return false; + }); + $('.formListings', page).on('submit', function () { + submitListingsForm(); + return false; + }); + $('.txtZipCode', page).on('change', function () { + refreshListings(this.value); + }); + page.querySelector('.chkAllTuners').addEventListener('change', function (e) { + if (e.target.checked) { + page.querySelector('.selectTunersSection').classList.add('hide'); + } else { + page.querySelector('.selectTunersSection').classList.remove('hide'); + } + }); + $('.createAccountHelp', page).html(globalize.translate('MessageCreateAccountAt', 'http://www.schedulesdirect.org')); + reload(); + }; +}; diff --git a/src/components/tvproviders/xmltv.js b/src/components/tvproviders/xmltv.js index 2203bc1fea..84e222fe09 100644 --- a/src/components/tvproviders/xmltv.js +++ b/src/components/tvproviders/xmltv.js @@ -1,191 +1,193 @@ -define(['jQuery', 'loading', 'globalize', 'emby-checkbox', 'emby-input', 'listViewStyle', 'paper-icon-button-light'], function ($, loading, globalize) { - 'use strict'; +import $ from 'jQuery'; +import loading from 'loading'; +import globalize from 'globalize'; +import 'emby-checkbox'; +import 'emby-input'; +import 'listViewStyle'; +import 'paper-icon-button-light'; - loading = loading.default || loading; +export default function (page, providerId, options) { + function getListingProvider(config, id) { + if (config && id) { + var result = config.ListingProviders.filter(function (provider) { + return provider.Id === id; + })[0]; - return function (page, providerId, options) { - function getListingProvider(config, id) { - if (config && id) { - var result = config.ListingProviders.filter(function (provider) { - return provider.Id === id; - })[0]; - - if (result) { - return Promise.resolve(result); - } - - return getListingProvider(); + if (result) { + return Promise.resolve(result); } - return ApiClient.getJSON(ApiClient.getUrl('LiveTv/ListingProviders/Default')); + return getListingProvider(); } - function reload() { - loading.show(); - ApiClient.getNamedConfiguration('livetv').then(function (config) { - getListingProvider(config, providerId).then(function (info) { - page.querySelector('.txtPath').value = info.Path || ''; - page.querySelector('.txtKids').value = (info.KidsCategories || []).join('|'); - page.querySelector('.txtNews').value = (info.NewsCategories || []).join('|'); - page.querySelector('.txtSports').value = (info.SportsCategories || []).join('|'); - page.querySelector('.txtMovies').value = (info.MovieCategories || []).join('|'); - page.querySelector('.txtMoviePrefix').value = info.MoviePrefix || ''; - page.querySelector('.txtUserAgent').value = info.UserAgent || ''; - page.querySelector('.chkAllTuners').checked = info.EnableAllTuners; + return ApiClient.getJSON(ApiClient.getUrl('LiveTv/ListingProviders/Default')); + } - if (page.querySelector('.chkAllTuners').checked) { - page.querySelector('.selectTunersSection').classList.add('hide'); - } else { - page.querySelector('.selectTunersSection').classList.remove('hide'); - } + function reload() { + loading.show(); + ApiClient.getNamedConfiguration('livetv').then(function (config) { + getListingProvider(config, providerId).then(function (info) { + page.querySelector('.txtPath').value = info.Path || ''; + page.querySelector('.txtKids').value = (info.KidsCategories || []).join('|'); + page.querySelector('.txtNews').value = (info.NewsCategories || []).join('|'); + page.querySelector('.txtSports').value = (info.SportsCategories || []).join('|'); + page.querySelector('.txtMovies').value = (info.MovieCategories || []).join('|'); + page.querySelector('.txtMoviePrefix').value = info.MoviePrefix || ''; + page.querySelector('.txtUserAgent').value = info.UserAgent || ''; + page.querySelector('.chkAllTuners').checked = info.EnableAllTuners; - refreshTunerDevices(page, info, config.TunerHosts); - loading.hide(); - }); - }); - } - - function getCategories(txtInput) { - var value = txtInput.value; - - if (value) { - return value.split('|'); - } - - return []; - } - - function submitListingsForm() { - loading.show(); - var id = providerId; - ApiClient.getNamedConfiguration('livetv').then(function (config) { - var info = config.ListingProviders.filter(function (provider) { - return provider.Id === id; - })[0] || {}; - info.Type = 'xmltv'; - info.Path = page.querySelector('.txtPath').value; - info.MoviePrefix = page.querySelector('.txtMoviePrefix').value || null; - info.UserAgent = page.querySelector('.txtUserAgent').value || null; - info.MovieCategories = getCategories(page.querySelector('.txtMovies')); - info.KidsCategories = getCategories(page.querySelector('.txtKids')); - info.NewsCategories = getCategories(page.querySelector('.txtNews')); - info.SportsCategories = getCategories(page.querySelector('.txtSports')); - info.EnableAllTuners = page.querySelector('.chkAllTuners').checked; - info.EnabledTuners = info.EnableAllTuners ? [] : $('.chkTuner', page).get().filter(function (tuner) { - return tuner.checked; - }).map(function (tuner) { - return tuner.getAttribute('data-id'); - }); - ApiClient.ajax({ - type: 'POST', - url: ApiClient.getUrl('LiveTv/ListingProviders', { - ValidateListings: true - }), - data: JSON.stringify(info), - contentType: 'application/json' - }).then(function (result) { - loading.hide(); - - if (options.showConfirmation !== false) { - Dashboard.processServerConfigurationUpdateResult(); - } - - Events.trigger(self, 'submitted'); - }, function () { - loading.hide(); - Dashboard.alert({ - message: globalize.translate('ErrorAddingXmlTvFile') - }); - }); - }); - } - - function getTunerName(providerId) { - switch (providerId = providerId.toLowerCase()) { - case 'm3u': - return 'M3U Playlist'; - case 'hdhomerun': - return 'HDHomerun'; - case 'satip': - return 'DVB'; - default: - return 'Unknown'; - } - } - - function refreshTunerDevices(page, providerInfo, devices) { - var html = ''; - - for (var i = 0, length = devices.length; i < length; i++) { - var device = devices[i]; - html += '
'; - var enabledTuners = providerInfo.EnabledTuners || []; - var isChecked = providerInfo.EnableAllTuners || enabledTuners.indexOf(device.Id) !== -1; - var checkedAttribute = isChecked ? ' checked' : ''; - html += ''; - html += '
'; - html += '
'; - html += device.FriendlyName || getTunerName(device.Type); - html += '
'; - html += '
'; - html += device.Url; - html += '
'; - html += '
'; - html += '
'; - } - - page.querySelector('.tunerList').innerHTML = html; - } - - function onSelectPathClick(e) { - var page = $(e.target).parents('.xmltvForm')[0]; - - require(['directorybrowser'], function (directoryBrowser) { - var picker = new directoryBrowser.default(); - picker.show({ - includeFiles: true, - callback: function (path) { - if (path) { - var txtPath = page.querySelector('.txtPath'); - txtPath.value = path; - txtPath.focus(); - } - picker.close(); - } - }); - }); - } - - var self = this; - - self.submit = function () { - page.querySelector('.btnSubmitListings').click(); - }; - - self.init = function () { - options = options || {}; - - // Only hide the buttons if explicitly set to false; default to showing if undefined or null - // FIXME: rename this option to clarify logic - var hideCancelButton = options.showCancelButton === false; - page.querySelector('.btnCancel').classList.toggle('hide', hideCancelButton); - - var hideSubmitButton = options.showSubmitButton === false; - page.querySelector('.btnSubmitListings').classList.toggle('hide', hideSubmitButton); - - $('form', page).on('submit', function () { - submitListingsForm(); - return false; - }); - page.querySelector('#btnSelectPath').addEventListener('click', onSelectPathClick); - page.querySelector('.chkAllTuners').addEventListener('change', function (evt) { - if (evt.target.checked) { + if (page.querySelector('.chkAllTuners').checked) { page.querySelector('.selectTunersSection').classList.add('hide'); } else { page.querySelector('.selectTunersSection').classList.remove('hide'); } + + refreshTunerDevices(page, info, config.TunerHosts); + loading.hide(); }); - reload(); - }; + }); + } + + function getCategories(txtInput) { + var value = txtInput.value; + + if (value) { + return value.split('|'); + } + + return []; + } + + function submitListingsForm() { + loading.show(); + var id = providerId; + ApiClient.getNamedConfiguration('livetv').then(function (config) { + var info = config.ListingProviders.filter(function (provider) { + return provider.Id === id; + })[0] || {}; + info.Type = 'xmltv'; + info.Path = page.querySelector('.txtPath').value; + info.MoviePrefix = page.querySelector('.txtMoviePrefix').value || null; + info.UserAgent = page.querySelector('.txtUserAgent').value || null; + info.MovieCategories = getCategories(page.querySelector('.txtMovies')); + info.KidsCategories = getCategories(page.querySelector('.txtKids')); + info.NewsCategories = getCategories(page.querySelector('.txtNews')); + info.SportsCategories = getCategories(page.querySelector('.txtSports')); + info.EnableAllTuners = page.querySelector('.chkAllTuners').checked; + info.EnabledTuners = info.EnableAllTuners ? [] : $('.chkTuner', page).get().filter(function (tuner) { + return tuner.checked; + }).map(function (tuner) { + return tuner.getAttribute('data-id'); + }); + ApiClient.ajax({ + type: 'POST', + url: ApiClient.getUrl('LiveTv/ListingProviders', { + ValidateListings: true + }), + data: JSON.stringify(info), + contentType: 'application/json' + }).then(function (result) { + loading.hide(); + + if (options.showConfirmation !== false) { + Dashboard.processServerConfigurationUpdateResult(); + } + + Events.trigger(self, 'submitted'); + }, function () { + loading.hide(); + Dashboard.alert({ + message: globalize.translate('ErrorAddingXmlTvFile') + }); + }); + }); + } + + function getTunerName(providerId) { + switch (providerId = providerId.toLowerCase()) { + case 'm3u': + return 'M3U Playlist'; + case 'hdhomerun': + return 'HDHomerun'; + case 'satip': + return 'DVB'; + default: + return 'Unknown'; + } + } + + function refreshTunerDevices(page, providerInfo, devices) { + var html = ''; + + for (var i = 0, length = devices.length; i < length; i++) { + var device = devices[i]; + html += '
'; + var enabledTuners = providerInfo.EnabledTuners || []; + var isChecked = providerInfo.EnableAllTuners || enabledTuners.indexOf(device.Id) !== -1; + var checkedAttribute = isChecked ? ' checked' : ''; + html += ''; + html += '
'; + html += '
'; + html += device.FriendlyName || getTunerName(device.Type); + html += '
'; + html += '
'; + html += device.Url; + html += '
'; + html += '
'; + html += '
'; + } + + page.querySelector('.tunerList').innerHTML = html; + } + + function onSelectPathClick(e) { + var page = $(e.target).parents('.xmltvForm')[0]; + + import('directorybrowser').then(({default: directoryBrowser}) => { + var picker = new directoryBrowser(); + picker.show({ + includeFiles: true, + callback: function (path) { + if (path) { + var txtPath = page.querySelector('.txtPath'); + txtPath.value = path; + txtPath.focus(); + } + picker.close(); + } + }); + }); + } + + var self = this; + + self.submit = function () { + page.querySelector('.btnSubmitListings').click(); }; -}); + + self.init = function () { + options = options || {}; + + // Only hide the buttons if explicitly set to false; default to showing if undefined or null + // FIXME: rename this option to clarify logic + var hideCancelButton = options.showCancelButton === false; + page.querySelector('.btnCancel').classList.toggle('hide', hideCancelButton); + + var hideSubmitButton = options.showSubmitButton === false; + page.querySelector('.btnSubmitListings').classList.toggle('hide', hideSubmitButton); + + $('form', page).on('submit', function () { + submitListingsForm(); + return false; + }); + page.querySelector('#btnSelectPath').addEventListener('click', onSelectPathClick); + page.querySelector('.chkAllTuners').addEventListener('change', function (evt) { + if (evt.target.checked) { + page.querySelector('.selectTunersSection').classList.add('hide'); + } else { + page.querySelector('.selectTunersSection').classList.remove('hide'); + } + }); + reload(); + }; +}; diff --git a/src/controllers/livetvguideprovider.js b/src/controllers/livetvguideprovider.js index 3ec04fd2af..2948fd5be2 100644 --- a/src/controllers/livetvguideprovider.js +++ b/src/controllers/livetvguideprovider.js @@ -11,7 +11,7 @@ define(['events', 'loading', 'globalize'], function (events, loading, globalize) var url = 'components/tvproviders/' + type + '.js'; require([url], function (factory) { - var instance = new factory(page, providerId, {}); + var instance = new factory.default(page, providerId, {}); events.on(instance, 'submitted', onListingsSubmitted); instance.init(); }); From 4af9b91c3b8d5cf6fabb858c481a2e070ad8269f Mon Sep 17 00:00:00 2001 From: Cameron Date: Mon, 3 Aug 2020 07:40:48 +0100 Subject: [PATCH 04/56] Update var declerations --- src/components/tvproviders/schedulesdirect.js | 58 +++++++++---------- src/components/tvproviders/xmltv.js | 34 +++++------ 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/components/tvproviders/schedulesdirect.js b/src/components/tvproviders/schedulesdirect.js index 9d60310e98..de469e1845 100644 --- a/src/components/tvproviders/schedulesdirect.js +++ b/src/components/tvproviders/schedulesdirect.js @@ -13,7 +13,7 @@ export default function (page, providerId, options) { function reload() { loading.show(); ApiClient.getNamedConfiguration('livetv').then(function (config) { - var info = config.ListingProviders.filter(function (i) { + const info = config.ListingProviders.filter(function (i) { return i.Id === providerId; })[0] || {}; listingsId = info.ListingsId; @@ -43,12 +43,12 @@ export default function (page, providerId, options) { function setCountry(info) { ApiClient.getJSON(ApiClient.getUrl('LiveTv/ListingProviders/SchedulesDirect/Countries')).then(function (result) { - var i; - var length; - var countryList = []; + let i; + let length; + const countryList = []; - for (var region in result) { - var countries = result[region]; + for (const region in result) { + const countries = result[region]; if (countries.length && region !== 'ZZZ') { for (i = 0, length = countries.length; i < length; i++) { @@ -88,20 +88,20 @@ export default function (page, providerId, options) { return Promise.resolve(''); } - var buffer = new TextEncoder('utf-8').encode(str); + const buffer = new TextEncoder('utf-8').encode(str); return crypto.subtle.digest('SHA-256', buffer).then(function (hash) { return hex(hash); }); } function hex(buffer) { - var hexCodes = []; - var view = new DataView(buffer); + const hexCodes = []; + const view = new DataView(buffer); - for (var i = 0; i < view.byteLength; i += 4) { - var value = view.getUint32(i); - var stringValue = value.toString(16); - var paddedValue = ('00000000' + stringValue).slice(-'00000000'.length); + for (let i = 0; i < view.byteLength; i += 4) { + const value = view.getUint32(i); + const stringValue = value.toString(16); + const paddedValue = ('00000000' + stringValue).slice(-'00000000'.length); hexCodes.push(paddedValue); } @@ -111,14 +111,14 @@ export default function (page, providerId, options) { function submitLoginForm() { loading.show(); sha256(page.querySelector('.txtPass').value).then(function (passwordHash) { - var info = { + const info = { Type: 'SchedulesDirect', Username: page.querySelector('.txtUser').value, EnableAllTuners: true, Password: passwordHash, Pw: page.querySelector('.txtPass').value }; - var id = providerId; + const id = providerId; if (id) { info.Id = id; @@ -145,7 +145,7 @@ export default function (page, providerId, options) { } function submitListingsForm() { - var selectedListingsId = $('#selectListing', page).val(); + const selectedListingsId = $('#selectListing', page).val(); if (!selectedListingsId) { return void Dashboard.alert({ @@ -154,9 +154,9 @@ export default function (page, providerId, options) { } loading.show(); - var id = providerId; + const id = providerId; ApiClient.getNamedConfiguration('livetv').then(function (config) { - var info = config.ListingProviders.filter(function (i) { + const info = config.ListingProviders.filter(function (i) { return i.Id === id; })[0]; info.ZipCode = page.querySelector('.txtZipCode').value; @@ -239,14 +239,14 @@ export default function (page, providerId, options) { } function refreshTunerDevices(page, providerInfo, devices) { - var html = ''; + let html = ''; - for (var i = 0, length = devices.length; i < length; i++) { - var device = devices[i]; + for (let i = 0, length = devices.length; i < length; i++) { + const device = devices[i]; html += '
'; - var enabledTuners = providerInfo.EnabledTuners || []; - var isChecked = providerInfo.EnableAllTuners || enabledTuners.indexOf(device.Id) !== -1; - var checkedAttribute = isChecked ? ' checked' : ''; + const enabledTuners = providerInfo.EnabledTuners || []; + const isChecked = providerInfo.EnableAllTuners || enabledTuners.indexOf(device.Id) !== -1; + const checkedAttribute = isChecked ? ' checked' : ''; html += ''; html += '
'; html += '
'; @@ -262,8 +262,8 @@ export default function (page, providerId, options) { page.querySelector('.tunerList').innerHTML = html; } - var listingsId; - var self = this; + let listingsId; + const self = this; self.submit = function () { page.querySelector('.btnSubmitListingsContainer').click(); @@ -274,10 +274,10 @@ export default function (page, providerId, options) { // Only hide the buttons if explicitly set to false; default to showing if undefined or null // FIXME: rename this option to clarify logic - var hideCancelButton = options.showCancelButton === false; + const hideCancelButton = options.showCancelButton === false; page.querySelector('.btnCancel').classList.toggle('hide', hideCancelButton); - var hideSubmitButton = options.showSubmitButton === false; + const hideSubmitButton = options.showSubmitButton === false; page.querySelector('.btnSubmitListings').classList.toggle('hide', hideSubmitButton); $('.formLogin', page).on('submit', function () { @@ -301,4 +301,4 @@ export default function (page, providerId, options) { $('.createAccountHelp', page).html(globalize.translate('MessageCreateAccountAt', 'http://www.schedulesdirect.org')); reload(); }; -}; +} diff --git a/src/components/tvproviders/xmltv.js b/src/components/tvproviders/xmltv.js index 84e222fe09..a75b29eeb3 100644 --- a/src/components/tvproviders/xmltv.js +++ b/src/components/tvproviders/xmltv.js @@ -9,7 +9,7 @@ import 'paper-icon-button-light'; export default function (page, providerId, options) { function getListingProvider(config, id) { if (config && id) { - var result = config.ListingProviders.filter(function (provider) { + const result = config.ListingProviders.filter(function (provider) { return provider.Id === id; })[0]; @@ -49,7 +49,7 @@ export default function (page, providerId, options) { } function getCategories(txtInput) { - var value = txtInput.value; + const value = txtInput.value; if (value) { return value.split('|'); @@ -60,9 +60,9 @@ export default function (page, providerId, options) { function submitListingsForm() { loading.show(); - var id = providerId; + const id = providerId; ApiClient.getNamedConfiguration('livetv').then(function (config) { - var info = config.ListingProviders.filter(function (provider) { + const info = config.ListingProviders.filter(function (provider) { return provider.Id === id; })[0] || {}; info.Type = 'xmltv'; @@ -117,14 +117,14 @@ export default function (page, providerId, options) { } function refreshTunerDevices(page, providerInfo, devices) { - var html = ''; + let html = ''; - for (var i = 0, length = devices.length; i < length; i++) { - var device = devices[i]; + for (let i = 0, length = devices.length; i < length; i++) { + const device = devices[i]; html += '
'; - var enabledTuners = providerInfo.EnabledTuners || []; - var isChecked = providerInfo.EnableAllTuners || enabledTuners.indexOf(device.Id) !== -1; - var checkedAttribute = isChecked ? ' checked' : ''; + const enabledTuners = providerInfo.EnabledTuners || []; + const isChecked = providerInfo.EnableAllTuners || enabledTuners.indexOf(device.Id) !== -1; + const checkedAttribute = isChecked ? ' checked' : ''; html += ''; html += '
'; html += '
'; @@ -141,15 +141,15 @@ export default function (page, providerId, options) { } function onSelectPathClick(e) { - var page = $(e.target).parents('.xmltvForm')[0]; + const page = $(e.target).parents('.xmltvForm')[0]; import('directorybrowser').then(({default: directoryBrowser}) => { - var picker = new directoryBrowser(); + const picker = new directoryBrowser(); picker.show({ includeFiles: true, callback: function (path) { if (path) { - var txtPath = page.querySelector('.txtPath'); + const txtPath = page.querySelector('.txtPath'); txtPath.value = path; txtPath.focus(); } @@ -159,7 +159,7 @@ export default function (page, providerId, options) { }); } - var self = this; + const self = this; self.submit = function () { page.querySelector('.btnSubmitListings').click(); @@ -170,10 +170,10 @@ export default function (page, providerId, options) { // Only hide the buttons if explicitly set to false; default to showing if undefined or null // FIXME: rename this option to clarify logic - var hideCancelButton = options.showCancelButton === false; + const hideCancelButton = options.showCancelButton === false; page.querySelector('.btnCancel').classList.toggle('hide', hideCancelButton); - var hideSubmitButton = options.showSubmitButton === false; + const hideSubmitButton = options.showSubmitButton === false; page.querySelector('.btnSubmitListings').classList.toggle('hide', hideSubmitButton); $('form', page).on('submit', function () { @@ -190,4 +190,4 @@ export default function (page, providerId, options) { }); reload(); }; -}; +} From bafe857271606fd65227e5176f490673b66fabed Mon Sep 17 00:00:00 2001 From: Xantios Krugor Date: Mon, 3 Aug 2020 14:20:31 +0200 Subject: [PATCH 05/56] Move focusManager to ES6 --- package.json | 1 + src/components/focusManager.js | 7 ++++--- src/controllers/list.js | 2 +- src/libraries/scroller.js | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index f794b8b6da..eae461bb4f 100644 --- a/package.json +++ b/package.json @@ -110,6 +110,7 @@ "src/components/favoriteitems.js", "src/components/fetchhelper.js", "src/components/filterdialog/filterdialog.js", + "src/components/focusManager.js", "src/components/groupedcards.js", "src/components/homeScreenSettings/homeScreenSettings.js", "src/components/homesections/homesections.js", diff --git a/src/components/focusManager.js b/src/components/focusManager.js index 9c495bf952..1f947871de 100644 --- a/src/components/focusManager.js +++ b/src/components/focusManager.js @@ -1,4 +1,6 @@ -define(['dom', 'scrollManager'], function (dom, scrollManager) { +import dom from 'dom'; +import scrollManager from 'scrollManager'; + 'use strict'; var scopes = []; @@ -472,7 +474,7 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { } } - return { + export default { autoFocus: autoFocus, focus: focus, focusableParent: focusableParent, @@ -505,4 +507,3 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { focusLast: focusLast, moveFocus: moveFocus }; -}); diff --git a/src/controllers/list.js b/src/controllers/list.js index 68e81f05dd..a35b7a0cf9 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -771,7 +771,7 @@ define(['globalize', 'listView', 'layoutManager', 'userSettings', 'focusManager' loading.hide(); if (refresh) { - focusManager.autoFocus(self.itemsContainer); + focusManager.default.autoFocus(self.itemsContainer); } }); diff --git a/src/libraries/scroller.js b/src/libraries/scroller.js index c0cb3e557c..d869d8c8be 100644 --- a/src/libraries/scroller.js +++ b/src/libraries/scroller.js @@ -697,7 +697,7 @@ define(['browser', 'layoutManager', 'dom', 'focusManager', 'ResizeObserver', 'sc function onFrameClick(e) { if (e.which === 1) { - var focusableParent = focusManager.focusableParent(e.target); + var focusableParent = focusManager.default.focusableParent(e.target); if (focusableParent && focusableParent !== document.activeElement) { focusableParent.focus(); } From 32e3df78010380c5c27d205a063fe647452d736e Mon Sep 17 00:00:00 2001 From: Xantios Krugor Date: Mon, 3 Aug 2020 14:20:31 +0200 Subject: [PATCH 06/56] Move focusManager to ES6 --- package.json | 1 + src/components/focusManager.js | 7 ++++--- src/controllers/list.js | 2 +- src/libraries/scroller.js | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index f794b8b6da..eae461bb4f 100644 --- a/package.json +++ b/package.json @@ -110,6 +110,7 @@ "src/components/favoriteitems.js", "src/components/fetchhelper.js", "src/components/filterdialog/filterdialog.js", + "src/components/focusManager.js", "src/components/groupedcards.js", "src/components/homeScreenSettings/homeScreenSettings.js", "src/components/homesections/homesections.js", diff --git a/src/components/focusManager.js b/src/components/focusManager.js index 9c495bf952..1f947871de 100644 --- a/src/components/focusManager.js +++ b/src/components/focusManager.js @@ -1,4 +1,6 @@ -define(['dom', 'scrollManager'], function (dom, scrollManager) { +import dom from 'dom'; +import scrollManager from 'scrollManager'; + 'use strict'; var scopes = []; @@ -472,7 +474,7 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { } } - return { + export default { autoFocus: autoFocus, focus: focus, focusableParent: focusableParent, @@ -505,4 +507,3 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { focusLast: focusLast, moveFocus: moveFocus }; -}); diff --git a/src/controllers/list.js b/src/controllers/list.js index 68e81f05dd..a35b7a0cf9 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -771,7 +771,7 @@ define(['globalize', 'listView', 'layoutManager', 'userSettings', 'focusManager' loading.hide(); if (refresh) { - focusManager.autoFocus(self.itemsContainer); + focusManager.default.autoFocus(self.itemsContainer); } }); diff --git a/src/libraries/scroller.js b/src/libraries/scroller.js index c0cb3e557c..d869d8c8be 100644 --- a/src/libraries/scroller.js +++ b/src/libraries/scroller.js @@ -697,7 +697,7 @@ define(['browser', 'layoutManager', 'dom', 'focusManager', 'ResizeObserver', 'sc function onFrameClick(e) { if (e.which === 1) { - var focusableParent = focusManager.focusableParent(e.target); + var focusableParent = focusManager.default.focusableParent(e.target); if (focusableParent && focusableParent !== document.activeElement) { focusableParent.focus(); } From 133e1c9085649f45f275e0d5a0a77d026ec28069 Mon Sep 17 00:00:00 2001 From: Xantios Krugor Date: Mon, 3 Aug 2020 14:28:20 +0200 Subject: [PATCH 07/56] Disable linter for this file --- src/components/focusManager.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/focusManager.js b/src/components/focusManager.js index 1f947871de..74df694ff6 100644 --- a/src/components/focusManager.js +++ b/src/components/focusManager.js @@ -1,3 +1,5 @@ +/* eslint-disable indent */ + import dom from 'dom'; import scrollManager from 'scrollManager'; From df1f9470e64ce97b6d78269750b00171df07a42a Mon Sep 17 00:00:00 2001 From: Xantios Krugor Date: Mon, 3 Aug 2020 14:46:48 +0200 Subject: [PATCH 08/56] ESLint is a magnificent piece of software that everybody should love /sarcasm --- src/components/focusManager.js | 72 ++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/src/components/focusManager.js b/src/components/focusManager.js index 74df694ff6..b55f933db6 100644 --- a/src/components/focusManager.js +++ b/src/components/focusManager.js @@ -3,7 +3,9 @@ import dom from 'dom'; import scrollManager from 'scrollManager'; - 'use strict'; +/* eslint-disable no-unused-expressions */ +'use strict'; +/* eslint-enable no-unused-expressions */ var scopes = []; function pushScope(elem) { @@ -476,36 +478,38 @@ import scrollManager from 'scrollManager'; } } - export default { - autoFocus: autoFocus, - focus: focus, - focusableParent: focusableParent, - getFocusableElements: getFocusableElements, - moveLeft: function (sourceElement, options) { - var container = options ? options.container : null; - var focusableElements = options ? options.focusableElements : null; - nav(sourceElement, 0, container, focusableElements); - }, - moveRight: function (sourceElement, options) { - var container = options ? options.container : null; - var focusableElements = options ? options.focusableElements : null; - nav(sourceElement, 1, container, focusableElements); - }, - moveUp: function (sourceElement, options) { - var container = options ? options.container : null; - var focusableElements = options ? options.focusableElements : null; - nav(sourceElement, 2, container, focusableElements); - }, - moveDown: function (sourceElement, options) { - var container = options ? options.container : null; - var focusableElements = options ? options.focusableElements : null; - nav(sourceElement, 3, container, focusableElements); - }, - sendText: sendText, - isCurrentlyFocusable: isCurrentlyFocusable, - pushScope: pushScope, - popScope: popScope, - focusFirst: focusFirst, - focusLast: focusLast, - moveFocus: moveFocus - }; +/* eslint-enable indent */ + +export default { + autoFocus: autoFocus, + focus: focus, + focusableParent: focusableParent, + getFocusableElements: getFocusableElements, + moveLeft: function (sourceElement, options) { + var container = options ? options.container : null; + var focusableElements = options ? options.focusableElements : null; + nav(sourceElement, 0, container, focusableElements); + }, + moveRight: function (sourceElement, options) { + var container = options ? options.container : null; + var focusableElements = options ? options.focusableElements : null; + nav(sourceElement, 1, container, focusableElements); + }, + moveUp: function (sourceElement, options) { + var container = options ? options.container : null; + var focusableElements = options ? options.focusableElements : null; + nav(sourceElement, 2, container, focusableElements); + }, + moveDown: function (sourceElement, options) { + var container = options ? options.container : null; + var focusableElements = options ? options.focusableElements : null; + nav(sourceElement, 3, container, focusableElements); + }, + sendText: sendText, + isCurrentlyFocusable: isCurrentlyFocusable, + pushScope: pushScope, + popScope: popScope, + focusFirst: focusFirst, + focusLast: focusLast, + moveFocus: moveFocus +}; From 6f78cdfde2a4094d110cdeeead802ece5c086d64 Mon Sep 17 00:00:00 2001 From: Xantios Krugor Date: Mon, 3 Aug 2020 15:08:17 +0200 Subject: [PATCH 09/56] Its build as ES6 module, no need for the strict --- src/components/focusManager.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/focusManager.js b/src/components/focusManager.js index b55f933db6..a9ec377cce 100644 --- a/src/components/focusManager.js +++ b/src/components/focusManager.js @@ -3,10 +3,6 @@ import dom from 'dom'; import scrollManager from 'scrollManager'; -/* eslint-disable no-unused-expressions */ -'use strict'; -/* eslint-enable no-unused-expressions */ - var scopes = []; function pushScope(elem) { scopes.push(elem); From 8dced0300d02a506a6c895a3c1d0bc4ee0e6f688 Mon Sep 17 00:00:00 2001 From: matjaz321 Date: Mon, 3 Aug 2020 20:51:40 +0200 Subject: [PATCH 10/56] Added livetvseriestimers.js to package.json --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 17d175b7e7..d9b7c0970e 100644 --- a/package.json +++ b/package.json @@ -207,6 +207,7 @@ "src/controllers/searchpage.js", "src/controllers/livetvtuner.js", "src/controllers/livetvstatus.js", + "src/controllers/livetv/livetvseriestimers.js", "src/controllers/shows/episodes.js", "src/controllers/shows/tvgenres.js", "src/controllers/shows/tvlatest.js", From ffa3396a8f5eabd88b89d85f11acb4fece56a619 Mon Sep 17 00:00:00 2001 From: matjaz321 Date: Mon, 3 Aug 2020 21:17:44 +0200 Subject: [PATCH 11/56] Migrated livetvschedule.js to ES6 module --- package.json | 1 + src/controllers/livetv/livetvschedule.js | 216 ++++++++++++----------- 2 files changed, 110 insertions(+), 107 deletions(-) diff --git a/package.json b/package.json index 1d7cf770d3..7d86744574 100644 --- a/package.json +++ b/package.json @@ -222,6 +222,7 @@ "src/controllers/livetvstatus.js", "src/controllers/livetvguideprovider.js", "src/controllers/livetvsettings.js", + "src/controllers/livetv/livetvschedule.js", "src/controllers/shows/episodes.js", "src/controllers/shows/tvgenres.js", "src/controllers/shows/tvlatest.js", diff --git a/src/controllers/livetv/livetvschedule.js b/src/controllers/livetv/livetvschedule.js index 4427bef5d1..df6bcedac9 100644 --- a/src/controllers/livetv/livetvschedule.js +++ b/src/controllers/livetv/livetvschedule.js @@ -1,122 +1,124 @@ -define(['layoutManager', 'cardBuilder', 'apphost', 'imageLoader', 'loading', 'scripts/livetvcomponents', 'emby-button', 'emby-itemscontainer'], function (layoutManager, cardBuilder, appHost, imageLoader, loading) { - 'use strict'; +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'; - loading = loading.default || loading; +function enableScrollX() { + return !layoutManager.desktop; +} - function enableScrollX() { - return !layoutManager.desktop; +function renderRecordings(elem, recordings, cardOptions) { + if (recordings.length) { + elem.classList.remove('hide'); + } else { + elem.classList.add('hide'); } - function renderRecordings(elem, recordings, cardOptions) { - if (recordings.length) { + const recordingItems = elem.querySelector('.recordingItems'); + + if (enableScrollX()) { + recordingItems.classList.add('scrollX'); + + if (layoutManager.tv) { + recordingItems.classList.add('smoothScrollX'); + } + + recordingItems.classList.add('hiddenScrollX'); + recordingItems.classList.remove('vertical-wrap'); + } else { + recordingItems.classList.remove('scrollX'); + recordingItems.classList.remove('smoothScrollX'); + recordingItems.classList.remove('hiddenScrollX'); + recordingItems.classList.add('vertical-wrap'); + } + + recordingItems.innerHTML = cardBuilder.getCardsHtml(Object.assign({ + items: recordings, + shape: enableScrollX() ? 'autooverflow' : 'auto', + showTitle: true, + showParentTitle: true, + coverImage: true, + cardLayout: false, + centerText: true, + allowBottomPadding: !enableScrollX(), + preferThumb: 'auto' + }, cardOptions || {})); + imageLoader.lazyChildren(recordingItems); +} + +function getBackdropShape() { + return enableScrollX() ? 'overflowBackdrop' : 'backdrop'; +} + +function renderActiveRecordings(context, promise) { + promise.then(function (result) { + renderRecordings(context.querySelector('#activeRecordings'), result.Items, { + shape: enableScrollX() ? 'autooverflow' : 'auto', + defaultShape: getBackdropShape(), + showParentTitle: false, + showParentTitleOrTitle: true, + showTitle: false, + showAirTime: true, + showAirEndTime: true, + showChannelName: true, + coverImage: true, + overlayText: false, + overlayMoreButton: true + }); + }); +} + +function renderTimers(context, timers, options) { + LiveTvHelpers.getTimersHtml(timers, options).then(function (html) { + const elem = context; + + if (html) { elem.classList.remove('hide'); } else { elem.classList.add('hide'); } - var recordingItems = elem.querySelector('.recordingItems'); + elem.querySelector('.recordingItems').innerHTML = html; + imageLoader.lazyChildren(elem); + }); +} - if (enableScrollX()) { - recordingItems.classList.add('scrollX'); +function renderUpcomingRecordings(context, promise) { + promise.then(function (result) { + renderTimers(context.querySelector('#upcomingRecordings'), result.Items); + loading.hide(); + }); +} - if (layoutManager.tv) { - recordingItems.classList.add('smoothScrollX'); - } +export default function (view, params, tabContent) { + let activeRecordingsPromise; + let upcomingRecordingsPromise; + const self = this; + tabContent.querySelector('#upcomingRecordings .recordingItems').addEventListener('timercancelled', function () { + self.preRender(); + self.renderTab(); + }); - recordingItems.classList.add('hiddenScrollX'); - recordingItems.classList.remove('vertical-wrap'); - } else { - recordingItems.classList.remove('scrollX'); - recordingItems.classList.remove('smoothScrollX'); - recordingItems.classList.remove('hiddenScrollX'); - recordingItems.classList.add('vertical-wrap'); - } - - recordingItems.innerHTML = cardBuilder.getCardsHtml(Object.assign({ - items: recordings, - shape: enableScrollX() ? 'autooverflow' : 'auto', - showTitle: true, - showParentTitle: true, - coverImage: true, - cardLayout: false, - centerText: true, - allowBottomPadding: !enableScrollX(), - preferThumb: 'auto' - }, cardOptions || {})); - imageLoader.lazyChildren(recordingItems); - } - - function getBackdropShape() { - return enableScrollX() ? 'overflowBackdrop' : 'backdrop'; - } - - function renderActiveRecordings(context, promise) { - promise.then(function (result) { - renderRecordings(context.querySelector('#activeRecordings'), result.Items, { - shape: enableScrollX() ? 'autooverflow' : 'auto', - defaultShape: getBackdropShape(), - showParentTitle: false, - showParentTitleOrTitle: true, - showTitle: false, - showAirTime: true, - showAirEndTime: true, - showChannelName: true, - coverImage: true, - overlayText: false, - overlayMoreButton: true - }); + self.preRender = function () { + activeRecordingsPromise = ApiClient.getLiveTvRecordings({ + UserId: Dashboard.getCurrentUserId(), + IsInProgress: true, + Fields: 'CanDelete,PrimaryImageAspectRatio,BasicSyncInfo', + EnableTotalRecordCount: false, + EnableImageTypes: 'Primary,Thumb,Backdrop' }); - } - - function renderTimers(context, timers, options) { - LiveTvHelpers.getTimersHtml(timers, options).then(function (html) { - var elem = context; - - if (html) { - elem.classList.remove('hide'); - } else { - elem.classList.add('hide'); - } - - elem.querySelector('.recordingItems').innerHTML = html; - imageLoader.lazyChildren(elem); + upcomingRecordingsPromise = ApiClient.getLiveTvTimers({ + IsActive: false, + IsScheduled: true }); - } - - function renderUpcomingRecordings(context, promise) { - promise.then(function (result) { - renderTimers(context.querySelector('#upcomingRecordings'), result.Items); - loading.hide(); - }); - } - - return function (view, params, tabContent) { - var activeRecordingsPromise; - var upcomingRecordingsPromise; - var self = this; - tabContent.querySelector('#upcomingRecordings .recordingItems').addEventListener('timercancelled', function () { - self.preRender(); - self.renderTab(); - }); - - self.preRender = function () { - activeRecordingsPromise = ApiClient.getLiveTvRecordings({ - UserId: Dashboard.getCurrentUserId(), - IsInProgress: true, - Fields: 'CanDelete,PrimaryImageAspectRatio,BasicSyncInfo', - EnableTotalRecordCount: false, - EnableImageTypes: 'Primary,Thumb,Backdrop' - }); - upcomingRecordingsPromise = ApiClient.getLiveTvTimers({ - IsActive: false, - IsScheduled: true - }); - }; - - self.renderTab = function () { - loading.show(); - renderActiveRecordings(tabContent, activeRecordingsPromise); - renderUpcomingRecordings(tabContent, upcomingRecordingsPromise); - }; }; -}); + + self.renderTab = function () { + loading.show(); + renderActiveRecordings(tabContent, activeRecordingsPromise); + renderUpcomingRecordings(tabContent, upcomingRecordingsPromise); + }; +}; From 1d747c9252dc5927aa3a21e8b9d85270eaae13b6 Mon Sep 17 00:00:00 2001 From: matjaz321 Date: Mon, 3 Aug 2020 21:21:39 +0200 Subject: [PATCH 12/56] Fixed linting errors --- src/controllers/dashboard/notifications/notifications/index.js | 1 - src/controllers/livetv/livetvschedule.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/controllers/dashboard/notifications/notifications/index.js b/src/controllers/dashboard/notifications/notifications/index.js index d12a5f2e61..b97403f8eb 100644 --- a/src/controllers/dashboard/notifications/notifications/index.js +++ b/src/controllers/dashboard/notifications/notifications/index.js @@ -1,5 +1,4 @@ import loading from 'loading'; -import libraryMenu from 'libraryMenu'; import globalize from 'globalize'; import 'listViewStyle'; import 'emby-button'; diff --git a/src/controllers/livetv/livetvschedule.js b/src/controllers/livetv/livetvschedule.js index df6bcedac9..d7bfbad059 100644 --- a/src/controllers/livetv/livetvschedule.js +++ b/src/controllers/livetv/livetvschedule.js @@ -121,4 +121,4 @@ export default function (view, params, tabContent) { renderActiveRecordings(tabContent, activeRecordingsPromise); renderUpcomingRecordings(tabContent, upcomingRecordingsPromise); }; -}; +} From 2eb2ec3d8a047fe1939a184301db0f94c8f9e324 Mon Sep 17 00:00:00 2001 From: matjaz321 Date: Mon, 3 Aug 2020 21:26:13 +0200 Subject: [PATCH 13/56] Migrated livetvrecordings.js to es6 module --- package.json | 1 + src/controllers/livetv/livetvrecordings.js | 201 +++++++++++---------- 2 files changed, 103 insertions(+), 99 deletions(-) diff --git a/package.json b/package.json index 1d7cf770d3..e98cb81a5d 100644 --- a/package.json +++ b/package.json @@ -222,6 +222,7 @@ "src/controllers/livetvstatus.js", "src/controllers/livetvguideprovider.js", "src/controllers/livetvsettings.js", + "src/controllers/livetv/livetvrecordings.js", "src/controllers/shows/episodes.js", "src/controllers/shows/tvgenres.js", "src/controllers/shows/tvlatest.js", diff --git a/src/controllers/livetv/livetvrecordings.js b/src/controllers/livetv/livetvrecordings.js index b0259bc89b..cb3bfeb7a6 100644 --- a/src/controllers/livetv/livetvrecordings.js +++ b/src/controllers/livetv/livetvrecordings.js @@ -1,111 +1,114 @@ -define(['layoutManager', 'loading', 'cardBuilder', 'apphost', 'imageLoader', 'scripts/livetvcomponents', 'listViewStyle', 'emby-itemscontainer'], function (layoutManager, loading, cardBuilder, appHost, imageLoader) { - 'use strict'; +import layoutManager from 'layoutManager'; +import loading from 'loading'; +import cardBuilder from 'cardBuilder'; +import appHost from 'apphost'; +import imageLoader from 'imageLoader'; +import 'scripts/livetvcomponents'; +import 'listViewStyle'; +import 'emby-itemscontainer'; - loading = loading.default || loading; - - function renderRecordings(elem, recordings, cardOptions, scrollX) { - if (!elem) { - return; - } - - if (recordings.length) { - elem.classList.remove('hide'); - } else { - elem.classList.add('hide'); - } - - var recordingItems = elem.querySelector('.recordingItems'); - - if (scrollX) { - recordingItems.classList.add('scrollX'); - recordingItems.classList.add('hiddenScrollX'); - recordingItems.classList.remove('vertical-wrap'); - } else { - recordingItems.classList.remove('scrollX'); - recordingItems.classList.remove('hiddenScrollX'); - recordingItems.classList.add('vertical-wrap'); - } - - recordingItems.innerHTML = cardBuilder.getCardsHtml(Object.assign({ - items: recordings, - shape: scrollX ? 'autooverflow' : 'auto', - defaultShape: scrollX ? 'overflowBackdrop' : 'backdrop', - showTitle: true, - showParentTitle: true, - coverImage: true, - cardLayout: false, - centerText: true, - allowBottomPadding: !scrollX, - preferThumb: 'auto', - overlayText: false - }, cardOptions || {})); - imageLoader.lazyChildren(recordingItems); +function renderRecordings(elem, recordings, cardOptions, scrollX) { + if (!elem) { + return; } - function renderLatestRecordings(context, promise) { - promise.then(function (result) { - renderRecordings(context.querySelector('#latestRecordings'), result.Items, { - showYear: true, - lines: 2 - }, false); - loading.hide(); - }); + if (recordings.length) { + elem.classList.remove('hide'); + } else { + elem.classList.add('hide'); } - function renderRecordingFolders(context, promise) { - promise.then(function (result) { - renderRecordings(context.querySelector('#recordingFolders'), result.Items, { - showYear: false, - showParentTitle: false - }, false); - }); + const recordingItems = elem.querySelector('.recordingItems'); + + if (scrollX) { + recordingItems.classList.add('scrollX'); + recordingItems.classList.add('hiddenScrollX'); + recordingItems.classList.remove('vertical-wrap'); + } else { + recordingItems.classList.remove('scrollX'); + recordingItems.classList.remove('hiddenScrollX'); + recordingItems.classList.add('vertical-wrap'); } - function onMoreClick(e) { - var type = this.getAttribute('data-type'); - var serverId = ApiClient.serverId(); + recordingItems.innerHTML = cardBuilder.getCardsHtml(Object.assign({ + items: recordings, + shape: scrollX ? 'autooverflow' : 'auto', + defaultShape: scrollX ? 'overflowBackdrop' : 'backdrop', + showTitle: true, + showParentTitle: true, + coverImage: true, + cardLayout: false, + centerText: true, + allowBottomPadding: !scrollX, + preferThumb: 'auto', + overlayText: false + }, cardOptions || {})); + imageLoader.lazyChildren(recordingItems); +} - switch (type) { - case 'latest': - Dashboard.navigate('list.html?type=Recordings&serverId=' + serverId); - } +function renderLatestRecordings(context, promise) { + promise.then(function (result) { + renderRecordings(context.querySelector('#latestRecordings'), result.Items, { + showYear: true, + lines: 2 + }, false); + loading.hide(); + }); +} + +function renderRecordingFolders(context, promise) { + promise.then(function (result) { + renderRecordings(context.querySelector('#recordingFolders'), result.Items, { + showYear: false, + showParentTitle: false + }, false); + }); +} + +function onMoreClick(e) { + const type = this.getAttribute('data-type'); + const serverId = ApiClient.serverId(); + + switch (type) { + case 'latest': + Dashboard.navigate('list.html?type=Recordings&serverId=' + serverId); + } +} + +export default function (view, params, tabContent) { + function enableFullRender() { + return new Date().getTime() - lastFullRender > 300000; } - return function (view, params, tabContent) { - function enableFullRender() { - return new Date().getTime() - lastFullRender > 300000; + let foldersPromise; + let latestPromise; + const self = this; + let lastFullRender = 0; + const moreButtons = tabContent.querySelectorAll('.more'); + + for (let i = 0, length = moreButtons.length; i < length; i++) { + moreButtons[i].addEventListener('click', onMoreClick); + } + + self.preRender = function () { + if (enableFullRender()) { + latestPromise = ApiClient.getLiveTvRecordings({ + UserId: Dashboard.getCurrentUserId(), + Limit: 12, + Fields: 'CanDelete,PrimaryImageAspectRatio,BasicSyncInfo', + EnableTotalRecordCount: false, + EnableImageTypes: 'Primary,Thumb,Backdrop' + }); + foldersPromise = ApiClient.getRecordingFolders(Dashboard.getCurrentUserId()); } - - var foldersPromise; - var latestPromise; - var self = this; - var lastFullRender = 0; - var moreButtons = tabContent.querySelectorAll('.more'); - - for (var i = 0, length = moreButtons.length; i < length; i++) { - moreButtons[i].addEventListener('click', onMoreClick); - } - - self.preRender = function () { - if (enableFullRender()) { - latestPromise = ApiClient.getLiveTvRecordings({ - UserId: Dashboard.getCurrentUserId(), - Limit: 12, - Fields: 'CanDelete,PrimaryImageAspectRatio,BasicSyncInfo', - EnableTotalRecordCount: false, - EnableImageTypes: 'Primary,Thumb,Backdrop' - }); - foldersPromise = ApiClient.getRecordingFolders(Dashboard.getCurrentUserId()); - } - }; - - self.renderTab = function () { - if (enableFullRender()) { - loading.show(); - renderLatestRecordings(tabContent, latestPromise); - renderRecordingFolders(tabContent, foldersPromise); - lastFullRender = new Date().getTime(); - } - }; }; -}); + + self.renderTab = function () { + if (enableFullRender()) { + loading.show(); + renderLatestRecordings(tabContent, latestPromise); + renderRecordingFolders(tabContent, foldersPromise); + lastFullRender = new Date().getTime(); + } + }; +} From ba3418450ebe8f954d1ad6f2300acdb882725909 Mon Sep 17 00:00:00 2001 From: Cameron Date: Sat, 25 Jul 2020 11:42:21 +0100 Subject: [PATCH 14/56] Migration of movies to ES6 modules --- package.json | 6 + src/controllers/movies/moviecollections.js | 74 +++++++------ src/controllers/movies/moviegenres.js | 60 +++++----- src/controllers/movies/movies.js | 117 ++++++++++---------- src/controllers/movies/moviesrecommended.js | 111 +++++++++++-------- src/controllers/movies/movietrailers.js | 75 +++++++------ 6 files changed, 244 insertions(+), 199 deletions(-) diff --git a/package.json b/package.json index 1d7cf770d3..678794aebc 100644 --- a/package.json +++ b/package.json @@ -212,6 +212,12 @@ "src/controllers/edititemmetadata.js", "src/controllers/favorites.js", "src/controllers/hometab.js", + "src/controllers/dashboard/plugins/repositories.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", diff --git a/src/controllers/movies/moviecollections.js b/src/controllers/movies/moviecollections.js index 7c1a5156d9..530117295c 100644 --- a/src/controllers/movies/moviecollections.js +++ b/src/controllers/movies/moviecollections.js @@ -1,13 +1,19 @@ -define(['loading', 'events', 'libraryBrowser', 'imageLoader', 'listView', 'cardBuilder', 'userSettings', 'globalize', 'emby-itemscontainer'], function (loading, events, libraryBrowser, imageLoader, listView, cardBuilder, userSettings, globalize) { - 'use strict'; +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'; - loading = loading.default || loading; - libraryBrowser = libraryBrowser.default || libraryBrowser; +/* eslint-disable indent */ - return function (view, params, tabContent) { + export default function (view, params, tabContent) { function getPageData(context) { - var key = getSavedQueryKey(context); - var pageData = data[key]; + const key = getSavedQueryKey(context); + let pageData = data[key]; if (!pageData) { pageData = data[key] = { @@ -48,8 +54,8 @@ define(['loading', 'events', 'libraryBrowser', 'imageLoader', 'listView', 'cardB } function onViewStyleChange() { - var viewStyle = self.getCurrentViewStyle(); - var itemsContainer = tabContent.querySelector('.itemsContainer'); + const viewStyle = self.getCurrentViewStyle(); + const itemsContainer = tabContent.querySelector('.itemsContainer'); if (viewStyle == 'List') { itemsContainer.classList.add('vertical-list'); @@ -65,7 +71,7 @@ define(['loading', 'events', 'libraryBrowser', 'imageLoader', 'listView', 'cardB function reloadItems(page) { loading.show(); isLoading = true; - var query = getQuery(page); + const query = getQuery(page); ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { function onNextPageClick() { if (isLoading) { @@ -90,8 +96,8 @@ define(['loading', 'events', 'libraryBrowser', 'imageLoader', 'listView', 'cardB } window.scrollTo(0, 0); - var html; - var pagingHtml = libraryBrowser.getQueryPagingHtml({ + let html; + const pagingHtml = libraryBrowser.getQueryPagingHtml({ startIndex: query.StartIndex, limit: query.Limit, totalRecordCount: result.TotalRecordCount, @@ -101,7 +107,7 @@ define(['loading', 'events', 'libraryBrowser', 'imageLoader', 'listView', 'cardB sortButton: false, filterButton: false }); - var viewStyle = self.getCurrentViewStyle(); + const viewStyle = self.getCurrentViewStyle(); if (viewStyle == 'Thumb') { html = cardBuilder.getCardsHtml({ items: result.Items, @@ -155,22 +161,21 @@ define(['loading', 'events', 'libraryBrowser', 'imageLoader', 'listView', 'cardB showTitle: true }); } - var i; - var length; - var elems = tabContent.querySelectorAll('.paging'); - for (i = 0, length = elems.length; i < length; i++) { - elems[i].innerHTML = pagingHtml; + let elems = tabContent.querySelectorAll('.paging'); + + for (const elem of elems) { + elem.innerHTML = pagingHtml; } elems = tabContent.querySelectorAll('.btnNextPage'); - for (i = 0, length = elems.length; i < length; i++) { - elems[i].addEventListener('click', onNextPageClick); + for (const elem of elems) { + elem.addEventListener('click', onNextPageClick); } elems = tabContent.querySelectorAll('.btnPreviousPage'); - for (i = 0, length = elems.length; i < length; i++) { - elems[i].addEventListener('click', onPreviousPageClick); + for (const elem of elems) { + elem.addEventListener('click', onPreviousPageClick); } if (!result.Items.length) { @@ -182,22 +187,22 @@ define(['loading', 'events', 'libraryBrowser', 'imageLoader', 'listView', 'cardB html += '
'; } - var itemsContainer = tabContent.querySelector('.itemsContainer'); + const itemsContainer = tabContent.querySelector('.itemsContainer'); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; - require(['autoFocuser'], function (autoFocuser) { + import('autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(page); }); }); } - var self = this; - var data = {}; - var isLoading = false; + const self = this; + const data = {}; + let isLoading = false; self.getCurrentViewStyle = function () { return getPageData(tabContent).view; @@ -230,21 +235,21 @@ define(['loading', 'events', 'libraryBrowser', 'imageLoader', 'listView', 'cardB button: e.target }); }); - var btnSelectView = tabContent.querySelector('.btnSelectView'); + const btnSelectView = tabContent.querySelector('.btnSelectView'); btnSelectView.addEventListener('click', function (e) { libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), 'List,Poster,PosterCard,Thumb,ThumbCard'.split(',')); }); btnSelectView.addEventListener('layoutchange', function (e) { - var viewStyle = e.detail.viewStyle; + const viewStyle = e.detail.viewStyle; getPageData(tabContent).view = viewStyle; libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle); getQuery(tabContent).StartIndex = 0; onViewStyleChange(); reloadItems(tabContent); }); - tabContent.querySelector('.btnNewCollection').addEventListener('click', function () { - require(['collectionEditor'], function (collectionEditor) { - var serverId = ApiClient.serverInfo().Id; + tabContent.querySelector('.btnNewCollection').addEventListener('click', () => { + import('collectionEditor').then(({default: collectionEditor}) => { + const serverId = ApiClient.serverInfo().Id; new collectionEditor.showEditor({ items: [], serverId: serverId @@ -261,5 +266,6 @@ define(['loading', 'events', 'libraryBrowser', 'imageLoader', 'listView', 'cardB }; self.destroy = function () {}; - }; -}); + } + +/* eslint-enable indent */ diff --git a/src/controllers/movies/moviegenres.js b/src/controllers/movies/moviegenres.js index 82ab4d4d4b..56fb88b20f 100644 --- a/src/controllers/movies/moviegenres.js +++ b/src/controllers/movies/moviegenres.js @@ -1,13 +1,20 @@ -define(['layoutManager', 'loading', 'libraryBrowser', 'cardBuilder', 'lazyLoader', 'apphost', 'globalize', 'appRouter', 'dom', 'emby-button'], function (layoutManager, loading, libraryBrowser, cardBuilder, lazyLoader, appHost, globalize, appRouter, dom) { - 'use strict'; +import layoutManager from 'layoutManager'; +import loading from 'loading'; +import libraryBrowser from 'libraryBrowser'; +import cardBuilder from 'cardBuilder'; +import lazyLoader from 'lazyLoader'; +import appHost from 'apphost'; +import globalize from 'globalize'; +import appRouter from 'appRouter'; +import dom from 'dom'; +import 'emby-button'; - loading = loading.default || loading; - libraryBrowser = libraryBrowser.default || libraryBrowser; +/* eslint-disable indent */ - return function (view, params, tabContent) { + export default function (view, params, tabContent) { function getPageData() { - var key = getSavedQueryKey(); - var pageData = data[key]; + const key = getSavedQueryKey(); + let pageData = data[key]; if (!pageData) { pageData = data[key] = { @@ -37,7 +44,7 @@ define(['layoutManager', 'loading', 'libraryBrowser', 'cardBuilder', 'lazyLoader function getPromise() { loading.show(); - var query = getQuery(); + const query = getQuery(); return ApiClient.getGenres(ApiClient.getCurrentUserId(), query); } @@ -54,17 +61,17 @@ define(['layoutManager', 'loading', 'libraryBrowser', 'cardBuilder', 'lazyLoader } function fillItemsContainer(entry) { - var elem = entry.target; - var id = elem.getAttribute('data-id'); - var viewStyle = self.getCurrentViewStyle(); - var limit = viewStyle == 'Thumb' || viewStyle == 'ThumbCard' ? 5 : 9; + const elem = entry.target; + const id = elem.getAttribute('data-id'); + const viewStyle = self.getCurrentViewStyle(); + let limit = 'Thumb' == viewStyle || 'ThumbCard' == viewStyle ? 5 : 9; if (enableScrollX()) { limit = 10; } - var enableImageTypes = viewStyle == 'Thumb' || viewStyle == 'ThumbCard' ? 'Primary,Backdrop,Thumb' : 'Primary'; - var query = { + const enableImageTypes = 'Thumb' == viewStyle || 'ThumbCard' == viewStyle ? 'Primary,Backdrop,Thumb' : 'Primary'; + const query = { SortBy: 'SortName', SortOrder: 'Ascending', IncludeItemTypes: 'Movie', @@ -129,14 +136,14 @@ define(['layoutManager', 'loading', 'libraryBrowser', 'cardBuilder', 'lazyLoader } function reloadItems(context, promise) { - var query = getQuery(); + const query = getQuery(); promise.then(function (result) { - var elem = context.querySelector('#items'); - var html = ''; - var items = result.Items; + const elem = context.querySelector('#items'); + let html = ''; + const items = result.Items; - for (var i = 0, length = items.length; i < length; i++) { - var item = items[i]; + for (let i = 0, length = items.length; i < length; i++) { + const item = items[i]; html += '
'; html += '
'; @@ -151,7 +158,7 @@ define(['layoutManager', 'loading', 'libraryBrowser', 'cardBuilder', 'lazyLoader html += ''; html += '
'; if (enableScrollX()) { - var scrollXClass = 'scrollX hiddenScrollX'; + let scrollXClass = 'scrollX hiddenScrollX'; if (layoutManager.tv) { scrollXClass += 'smoothScrollX padded-top-focusscale padded-bottom-focusscale'; @@ -187,8 +194,8 @@ define(['layoutManager', 'loading', 'libraryBrowser', 'cardBuilder', 'lazyLoader self.renderTab(); } - var self = this; - var data = {}; + const self = this; + const data = {}; self.getViewStyles = function () { return 'Poster,PosterCard,Thumb,ThumbCard'.split(','); @@ -205,7 +212,7 @@ define(['layoutManager', 'loading', 'libraryBrowser', 'cardBuilder', 'lazyLoader }; self.enableViewSelection = true; - var promise; + let promise; self.preRender = function () { promise = getPromise(); @@ -214,5 +221,6 @@ define(['layoutManager', 'loading', 'libraryBrowser', 'cardBuilder', 'lazyLoader self.renderTab = function () { reloadItems(tabContent, promise); }; - }; -}); + } + +/* eslint-enable indent */ diff --git a/src/controllers/movies/movies.js b/src/controllers/movies/movies.js index ade9dc4b89..3b68849036 100644 --- a/src/controllers/movies/movies.js +++ b/src/controllers/movies/movies.js @@ -1,12 +1,19 @@ -define(['loading', 'layoutManager', 'userSettings', 'events', 'libraryBrowser', 'alphaPicker', 'listView', 'cardBuilder', 'globalize', 'emby-itemscontainer'], function (loading, layoutManager, userSettings, events, libraryBrowser, AlphaPicker, listView, cardBuilder, globalize) { - 'use strict'; +import loading from 'loading'; +import layoutManager from 'layoutManager'; +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'; - loading = loading.default || loading; - libraryBrowser = libraryBrowser.default || libraryBrowser; +/* eslint-disable indent */ - return function (view, params, tabContent, options) { - function onViewStyleChange() { - if (self.getCurrentViewStyle() == 'List') { + export default function (view, params, tabContent, options) { + const onViewStyleChange = () => { + if (this.getCurrentViewStyle() == 'List') { itemsContainer.classList.add('vertical-list'); itemsContainer.classList.remove('vertical-wrap'); } else { @@ -15,13 +22,13 @@ define(['loading', 'layoutManager', 'userSettings', 'events', 'libraryBrowser', } itemsContainer.innerHTML = ''; - } + }; - function updateFilterControls() { - if (self.alphaPicker) { - self.alphaPicker.value(query.NameStartsWithOrGreater); + const updateFilterControls = () => { + if (this.alphaPicker) { + this.alphaPicker.value(query.NameStartsWithOrGreater); } - } + }; function fetchData() { isLoading = true; @@ -54,7 +61,7 @@ define(['loading', 'layoutManager', 'userSettings', 'events', 'libraryBrowser', window.scrollTo(0, 0); updateFilterControls(); - var pagingHtml = libraryBrowser.getQueryPagingHtml({ + const pagingHtml = libraryBrowser.getQueryPagingHtml({ startIndex: query.StartIndex, limit: query.Limit, totalRecordCount: result.TotalRecordCount, @@ -64,35 +71,30 @@ define(['loading', 'layoutManager', 'userSettings', 'events', 'libraryBrowser', sortButton: false, filterButton: false }); - var i; - var length; - var elems = tabContent.querySelectorAll('.paging'); - for (i = 0, length = elems.length; i < length; i++) { - elems[i].innerHTML = pagingHtml; + for (const elem of tabContent.querySelectorAll('.paging')) { + elem.innerHTML = pagingHtml; } - elems = tabContent.querySelectorAll('.btnNextPage'); - for (i = 0, length = elems.length; i < length; i++) { - elems[i].addEventListener('click', onNextPageClick); + for (const elem of tabContent.querySelectorAll('.btnNextPage')) { + elem.addEventListener('click', onNextPageClick); } - elems = tabContent.querySelectorAll('.btnPreviousPage'); - for (i = 0, length = elems.length; i < length; i++) { - elems[i].addEventListener('click', onPreviousPageClick); + for (const elem of tabContent.querySelectorAll('.btnPreviousPage')) { + elem.addEventListener('click', onPreviousPageClick); } isLoading = false; loading.hide(); - require(['autoFocuser'], function (autoFocuser) { + import('autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(tabContent); }); } - function getItemsHtml(items) { - var html; - var viewStyle = self.getCurrentViewStyle(); + const getItemsHtml = (items) => { + let html; + const viewStyle = this.getCurrentViewStyle(); if (viewStyle == 'Thumb') { html = cardBuilder.getCardsHtml({ @@ -156,22 +158,22 @@ define(['loading', 'layoutManager', 'userSettings', 'events', 'libraryBrowser', } return html; - } + }; - function initPage(tabContent) { + const initPage = (tabContent) => { itemsContainer.fetchData = fetchData; itemsContainer.getItemsHtml = getItemsHtml; itemsContainer.afterRefresh = afterRefresh; - var alphaPickerElement = tabContent.querySelector('.alphaPicker'); + let alphaPickerElement = tabContent.querySelector('.alphaPicker'); if (alphaPickerElement) { alphaPickerElement.addEventListener('alphavaluechanged', function (e) { - var newValue = e.detail.value; + let newValue = e.detail.value; query.NameStartsWithOrGreater = newValue; query.StartIndex = 0; itemsContainer.refreshItems(); }); - self.alphaPicker = new AlphaPicker.default({ + this.alphaPicker = new AlphaPicker({ element: alphaPickerElement, valueChangeEvent: 'click' }); @@ -181,14 +183,14 @@ define(['loading', 'layoutManager', 'userSettings', 'events', 'libraryBrowser', itemsContainer.classList.add('padded-right-withalphapicker'); } - var btnFilter = tabContent.querySelector('.btnFilter'); + const btnFilter = tabContent.querySelector('.btnFilter'); if (btnFilter) { - btnFilter.addEventListener('click', function () { - self.showFilterMenu(); + btnFilter.addEventListener('click', () => { + this.showFilterMenu(); }); } - var btnSort = tabContent.querySelector('.btnSort'); + const btnSort = tabContent.querySelector('.btnSort'); if (btnSort) { btnSort.addEventListener('click', function (e) { @@ -231,24 +233,23 @@ define(['loading', 'layoutManager', 'userSettings', 'events', 'libraryBrowser', }); }); } - var btnSelectView = tabContent.querySelector('.btnSelectView'); + const btnSelectView = tabContent.querySelector('.btnSelectView'); btnSelectView.addEventListener('click', function (e) { - libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), 'Banner,List,Poster,PosterCard,Thumb,ThumbCard'.split(',')); + libraryBrowser.showLayoutMenu(e.target, this.getCurrentViewStyle, 'Banner,List,Poster,PosterCard,Thumb,ThumbCard'.split(',')); }); btnSelectView.addEventListener('layoutchange', function (e) { - var viewStyle = e.detail.viewStyle; + let viewStyle = e.detail.viewStyle; userSettings.set(savedViewKey, viewStyle); query.StartIndex = 0; onViewStyleChange(); itemsContainer.refreshItems(); }); - } + }; - var self = this; - var itemsContainer = tabContent.querySelector('.itemsContainer'); - var savedQueryKey = params.topParentId + '-' + options.mode; - var savedViewKey = savedQueryKey + '-view'; - var query = { + let itemsContainer = tabContent.querySelector('.itemsContainer'); + const savedQueryKey = params.topParentId + '-' + options.mode; + const savedViewKey = savedQueryKey + '-view'; + let query = { SortBy: 'SortName,ProductionYear', SortOrder: 'Ascending', IncludeItemTypes: 'Movie', @@ -264,7 +265,7 @@ define(['loading', 'layoutManager', 'userSettings', 'events', 'libraryBrowser', query['Limit'] = userSettings.libraryPageSize(); } - var isLoading = false; + let isLoading = false; if (options.mode === 'favorites') { query.IsFavorite = true; @@ -272,14 +273,14 @@ define(['loading', 'layoutManager', 'userSettings', 'events', 'libraryBrowser', query = userSettings.loadQuerySettings(savedQueryKey, query); - self.showFilterMenu = function () { - require(['components/filterdialog/filterdialog'], function ({default: filterDialogFactory}) { - var filterDialog = new filterDialogFactory({ + this.showFilterMenu = function () { + import('components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { + let filterDialog = new filterDialogFactory({ query: query, mode: 'movies', serverId: ApiClient.serverId() }); - events.on(filterDialog, 'filterchange', function () { + events.on(filterDialog, 'filterchange', () => { query.StartIndex = 0; itemsContainer.refreshItems(); }); @@ -287,22 +288,24 @@ define(['loading', 'layoutManager', 'userSettings', 'events', 'libraryBrowser', }); }; - self.getCurrentViewStyle = function () { + this.getCurrentViewStyle = function () { return userSettings.get(savedViewKey) || 'Poster'; }; - self.initTab = function () { + this.initTab = function () { initPage(tabContent); onViewStyleChange(); }; - self.renderTab = function () { + //function renderTab () { + this.renderTab = function () { itemsContainer.refreshItems(); updateFilterControls(); }; - self.destroy = function () { + this.destroy = function () { itemsContainer = null; }; - }; -}); + } + +/* eslint-enable indent */ diff --git a/src/controllers/movies/moviesrecommended.js b/src/controllers/movies/moviesrecommended.js index a633d654cd..5e376637b3 100644 --- a/src/controllers/movies/moviesrecommended.js +++ b/src/controllers/movies/moviesrecommended.js @@ -1,5 +1,20 @@ -define(['events', 'layoutManager', 'inputManager', 'userSettings', 'libraryMenu', 'mainTabsManager', 'cardBuilder', 'dom', 'imageLoader', 'playbackManager', 'globalize', 'emby-scroller', 'emby-itemscontainer', 'emby-tabs', 'emby-button'], function (events, layoutManager, inputManager, userSettings, libraryMenu, mainTabsManager, cardBuilder, dom, imageLoader, playbackManager, globalize) { - 'use strict'; +import events from 'events'; +import layoutManager from 'layoutManager'; +import inputManager from 'inputManager'; +import * as userSettings from 'userSettings'; +import libraryMenu from 'libraryMenu'; +import 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'; + +/* eslint-disable indent */ playbackManager = playbackManager.default || playbackManager; @@ -16,7 +31,7 @@ define(['events', 'layoutManager', 'inputManager', 'userSettings', 'libraryMenu' } function loadLatest(page, userId, parentId) { - var options = { + const options = { IncludeItemTypes: 'Movie', Limit: 18, Fields: 'PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo', @@ -26,8 +41,8 @@ define(['events', 'layoutManager', 'inputManager', 'userSettings', 'libraryMenu' EnableTotalRecordCount: false }; ApiClient.getJSON(ApiClient.getUrl('Users/' + userId + '/Items/Latest', options)).then(function (items) { - var allowBottomPadding = !enableScrollX(); - var container = page.querySelector('#recentlyAddedItems'); + const allowBottomPadding = !enableScrollX(); + const container = page.querySelector('#recentlyAddedItems'); cardBuilder.buildCards(items, { itemsContainer: container, shape: getPortraitShape(), @@ -45,8 +60,8 @@ define(['events', 'layoutManager', 'inputManager', 'userSettings', 'libraryMenu' } function loadResume(page, userId, parentId) { - var screenWidth = dom.getWindowSize().innerWidth; - var options = { + let screenWidth = dom.getWindowSize().innerWidth; + const options = { SortBy: 'DatePlayed', SortOrder: 'Descending', IncludeItemTypes: 'Movie', @@ -67,8 +82,8 @@ define(['events', 'layoutManager', 'inputManager', 'userSettings', 'libraryMenu' page.querySelector('#resumableSection').classList.add('hide'); } - var allowBottomPadding = !enableScrollX(); - var container = page.querySelector('#resumableItems'); + const allowBottomPadding = !enableScrollX(); + const container = page.querySelector('#resumableItems'); cardBuilder.buildCards(result.Items, { itemsContainer: container, preferThumb: true, @@ -88,8 +103,8 @@ define(['events', 'layoutManager', 'inputManager', 'userSettings', 'libraryMenu' } function getRecommendationHtml(recommendation) { - var html = ''; - var title = ''; + let html = ''; + let title = ''; switch (recommendation.RecommendationType) { case 'SimilarToRecentlyPlayed': @@ -113,7 +128,7 @@ define(['events', 'layoutManager', 'inputManager', 'userSettings', 'libraryMenu' html += '
'; html += '

' + title + '

'; - var allowBottomPadding = true; + const allowBottomPadding = true; if (enableScrollX()) { html += '
'; @@ -141,8 +156,8 @@ define(['events', 'layoutManager', 'inputManager', 'userSettings', 'libraryMenu' } function loadSuggestions(page, userId, parentId) { - var screenWidth = dom.getWindowSize().innerWidth; - var url = ApiClient.getUrl('Movies/Recommendations', { + let screenWidth = dom.getWindowSize().innerWidth; + let url = ApiClient.getUrl('Movies/Recommendations', { userId: userId, categoryLimit: 6, ItemLimit: screenWidth >= 1920 ? 8 : screenWidth >= 1600 ? 8 : screenWidth >= 1200 ? 6 : 5, @@ -157,9 +172,9 @@ define(['events', 'layoutManager', 'inputManager', 'userSettings', 'libraryMenu' return; } - var html = recommendations.map(getRecommendationHtml).join(''); + const html = recommendations.map(getRecommendationHtml).join(''); page.querySelector('.noItemsMessage').classList.add('hide'); - var recs = page.querySelector('.recommendations'); + let recs = page.querySelector('.recommendations'); recs.innerHTML = html; imageLoader.lazyChildren(recs); @@ -169,7 +184,7 @@ define(['events', 'layoutManager', 'inputManager', 'userSettings', 'libraryMenu' } function autoFocus(page) { - require(['autoFocuser'], function (autoFocuser) { + import('autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(page); }); } @@ -195,17 +210,16 @@ define(['events', 'layoutManager', 'inputManager', 'userSettings', 'libraryMenu' } function initSuggestedTab(page, tabContent) { - var containers = tabContent.querySelectorAll('.itemsContainer'); + const containers = tabContent.querySelectorAll('.itemsContainer'); - for (var i = 0, length = containers.length; i < length; i++) { - setScrollClasses(containers[i], enableScrollX()); + for (const container of containers) { + setScrollClasses(container, enableScrollX()); } } function loadSuggestionsTab(view, params, tabContent) { - var parentId = params.topParentId; - var userId = ApiClient.getCurrentUserId(); - console.debug('loadSuggestionsTab'); + const parentId = params.topParentId; + const userId = ApiClient.getCurrentUserId(); loadResume(tabContent, userId, parentId); loadLatest(tabContent, userId, parentId); loadSuggestions(tabContent, userId, parentId); @@ -249,13 +263,13 @@ define(['events', 'layoutManager', 'inputManager', 'userSettings', 'libraryMenu' } } - return function (view, params) { + export default function (view, params) { function onBeforeTabChange(e) { preLoadTab(view, parseInt(e.detail.selectedTabIndex)); } function onTabChange(e) { - var newIndex = parseInt(e.detail.selectedTabIndex); + const newIndex = parseInt(e.detail.selectedTabIndex); loadTab(view, newIndex); } @@ -268,45 +282,47 @@ define(['events', 'layoutManager', 'inputManager', 'userSettings', 'libraryMenu' } function getTabController(page, index, callback) { - var depends = []; + let depends = ''; switch (index) { case 0: - depends.push('controllers/movies/movies'); + depends = 'controllers/movies/movies'; break; case 1: + depends = 'controllers/movies/moviesrecommended.js'; break; case 2: - depends.push('controllers/movies/movietrailers'); + depends = 'controllers/movies/movietrailers'; break; case 3: - depends.push('controllers/movies/movies'); + depends = 'controllers/movies/movies'; break; case 4: - depends.push('controllers/movies/moviecollections'); + depends = 'controllers/movies/moviecollections'; break; case 5: - depends.push('controllers/movies/moviegenres'); + depends = 'controllers/movies/moviegenres'; break; case 6: - depends.push('scripts/searchtab'); + depends = 'scripts/searchtab'; + break; } - require(depends, function (controllerFactory) { - var tabContent; + import(depends).then(({default: controllerFactory}) => { + let tabContent; if (index === suggestionsTabIndex) { tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); self.tabContent = tabContent; } - var controller = tabControllers[index]; + let controller = tabControllers[index]; if (!controller) { tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); @@ -375,17 +391,17 @@ define(['events', 'layoutManager', 'inputManager', 'userSettings', 'libraryMenu' var suggestionsTabIndex = 1; self.initTab = function () { - var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); + let tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); initSuggestedTab(view, tabContent); }; self.renderTab = function () { - var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); + let tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); loadSuggestionsTab(view, params, tabContent); }; - var tabControllers = []; - var renderedTabs = []; + let tabControllers = []; + let renderedTabs = []; view.addEventListener('viewshow', function (e) { initTabs(); if (!view.getAttribute('data-title')) { @@ -408,12 +424,11 @@ define(['events', 'layoutManager', 'inputManager', 'userSettings', 'libraryMenu' view.addEventListener('viewbeforehide', function (e) { inputManager.off(window, onInputCommand); }); - view.addEventListener('viewdestroy', function (e) { - tabControllers.forEach(function (t) { - if (t.destroy) { - t.destroy(); - } - }); - }); - }; -}); + for (const tabController of tabControllers) { + if (tabController.destroy) { + tabController.destroy(); + } + } + } + +/* eslint-enable indent */ diff --git a/src/controllers/movies/movietrailers.js b/src/controllers/movies/movietrailers.js index 8d9fe8d090..a892769e47 100644 --- a/src/controllers/movies/movietrailers.js +++ b/src/controllers/movies/movietrailers.js @@ -1,13 +1,21 @@ -define(['layoutManager', 'loading', 'events', 'libraryBrowser', 'imageLoader', 'alphaPicker', 'listView', 'cardBuilder', 'userSettings', 'globalize', 'emby-itemscontainer'], function (layoutManager, loading, events, libraryBrowser, imageLoader, AlphaPicker, listView, cardBuilder, userSettings, globalize) { - 'use strict'; +import layoutManager from 'layoutManager'; +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'; - loading = loading.default || loading; - libraryBrowser = libraryBrowser.default || libraryBrowser; +/* eslint-disable indent */ - return function (view, params, tabContent) { + export default function (view, params, tabContent) { function getPageData(context) { - var key = getSavedQueryKey(context); - var pageData = data[key]; + const key = getSavedQueryKey(context); + let pageData = data[key]; if (!pageData) { pageData = data[key] = { @@ -49,7 +57,7 @@ define(['layoutManager', 'loading', 'events', 'libraryBrowser', 'imageLoader', ' function reloadItems() { loading.show(); isLoading = true; - var query = getQuery(tabContent); + const query = getQuery(tabContent); ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { function onNextPageClick() { if (isLoading) { @@ -75,7 +83,7 @@ define(['layoutManager', 'loading', 'events', 'libraryBrowser', 'imageLoader', ' window.scrollTo(0, 0); updateFilterControls(tabContent); - var pagingHtml = libraryBrowser.getQueryPagingHtml({ + const pagingHtml = libraryBrowser.getQueryPagingHtml({ startIndex: query.StartIndex, limit: query.Limit, totalRecordCount: result.TotalRecordCount, @@ -85,8 +93,8 @@ define(['layoutManager', 'loading', 'events', 'libraryBrowser', 'imageLoader', ' sortButton: false, filterButton: false }); - var html; - var viewStyle = self.getCurrentViewStyle(); + let html; + const viewStyle = self.getCurrentViewStyle(); if (viewStyle == 'Thumb') { html = cardBuilder.getCardsHtml({ @@ -142,22 +150,20 @@ define(['layoutManager', 'loading', 'events', 'libraryBrowser', 'imageLoader', ' }); } - var i; - var length; - var elems = tabContent.querySelectorAll('.paging'); + let elems = tabContent.querySelectorAll('.paging'); - for (i = 0, length = elems.length; i < length; i++) { - elems[i].innerHTML = pagingHtml; + for (const elem of elems) { + elem.innerHTML = pagingHtml; } elems = tabContent.querySelectorAll('.btnNextPage'); - for (i = 0, length = elems.length; i < length; i++) { - elems[i].addEventListener('click', onNextPageClick); + for (const elem of elems) { + elem.addEventListener('click', onNextPageClick); } elems = tabContent.querySelectorAll('.btnPreviousPage'); - for (i = 0, length = elems.length; i < length; i++) { - elems[i].addEventListener('click', onPreviousPageClick); + for (const elem of elems) { + elem.addEventListener('click', onPreviousPageClick); } if (!result.Items.length) { @@ -169,7 +175,7 @@ define(['layoutManager', 'loading', 'events', 'libraryBrowser', 'imageLoader', ' html += '
'; } - var itemsContainer = tabContent.querySelector('.itemsContainer'); + const itemsContainer = tabContent.querySelector('.itemsContainer'); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(tabContent), query); @@ -179,17 +185,17 @@ define(['layoutManager', 'loading', 'events', 'libraryBrowser', 'imageLoader', ' } function updateFilterControls(tabContent) { - var query = getQuery(tabContent); + const query = getQuery(tabContent); self.alphaPicker.value(query.NameStartsWithOrGreater); } - var self = this; - var data = {}; - var isLoading = false; + const self = this; + const data = {}; + let isLoading = false; self.showFilterMenu = function () { - require(['components/filterdialog/filterdialog'], function ({default: filterDialogFactory}) { - var filterDialog = new filterDialogFactory({ + import('components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { + const filterDialog = new filterDialogFactory({ query: getQuery(tabContent), mode: 'movies', serverId: ApiClient.serverId() @@ -207,16 +213,16 @@ define(['layoutManager', 'loading', 'events', 'libraryBrowser', 'imageLoader', ' }; function initPage(tabContent) { - var alphaPickerElement = tabContent.querySelector('.alphaPicker'); - var itemsContainer = tabContent.querySelector('.itemsContainer'); + const alphaPickerElement = tabContent.querySelector('.alphaPicker'); + const itemsContainer = tabContent.querySelector('.itemsContainer'); alphaPickerElement.addEventListener('alphavaluechanged', function (e) { - var newValue = e.detail.value; - var query = getQuery(tabContent); + const newValue = e.detail.value; + const query = getQuery(tabContent); query.NameStartsWithOrGreater = newValue; query.StartIndex = 0; reloadItems(); }); - self.alphaPicker = new AlphaPicker.default({ + self.alphaPicker = new AlphaPicker({ element: alphaPickerElement, valueChangeEvent: 'click' }); @@ -270,5 +276,6 @@ define(['layoutManager', 'loading', 'events', 'libraryBrowser', 'imageLoader', ' }; self.destroy = function () {}; - }; -}); + } + +/* eslint-enable indent */ From f1b2a86c7d8047775bae0b9bf1bae1c60e14ee3e Mon Sep 17 00:00:00 2001 From: Cameron Date: Sat, 25 Jul 2020 22:36:23 +0100 Subject: [PATCH 15/56] Apply suggestions --- src/controllers/movies/moviecollections.js | 27 +++++++++---------- src/controllers/movies/moviegenres.js | 27 +++++++++---------- src/controllers/movies/movies.js | 1 - src/controllers/movies/movietrailers.js | 31 +++++++++++----------- 4 files changed, 41 insertions(+), 45 deletions(-) diff --git a/src/controllers/movies/moviecollections.js b/src/controllers/movies/moviecollections.js index 530117295c..ffedb10eef 100644 --- a/src/controllers/movies/moviecollections.js +++ b/src/controllers/movies/moviecollections.js @@ -53,8 +53,8 @@ import 'emby-itemscontainer'; return context.savedQueryKey; } - function onViewStyleChange() { - const viewStyle = self.getCurrentViewStyle(); + const onViewStyleChange = () => { + const viewStyle = this.getCurrentViewStyle(); const itemsContainer = tabContent.querySelector('.itemsContainer'); if (viewStyle == 'List') { @@ -66,13 +66,13 @@ import 'emby-itemscontainer'; } itemsContainer.innerHTML = ''; - } + }; - function reloadItems(page) { + const reloadItems = (page) => { loading.show(); isLoading = true; const query = getQuery(page); - ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { + ApiClient.getItems(ApiClient.getCurrentUserId(), query).then((result) => { function onNextPageClick() { if (isLoading) { return; @@ -107,7 +107,7 @@ import 'emby-itemscontainer'; sortButton: false, filterButton: false }); - const viewStyle = self.getCurrentViewStyle(); + const viewStyle = this.getCurrentViewStyle(); if (viewStyle == 'Thumb') { html = cardBuilder.getCardsHtml({ items: result.Items, @@ -198,17 +198,16 @@ import 'emby-itemscontainer'; autoFocuser.autoFocus(page); }); }); - } + }; - const self = this; const data = {}; let isLoading = false; - self.getCurrentViewStyle = function () { + this.getCurrentViewStyle = function () { return getPageData(tabContent).view; }; - function initPage(tabContent) { + const initPage = (tabContent) => { tabContent.querySelector('.btnSort').addEventListener('click', function (e) { libraryBrowser.showSortMenu({ items: [{ @@ -237,7 +236,7 @@ import 'emby-itemscontainer'; }); const btnSelectView = tabContent.querySelector('.btnSelectView'); btnSelectView.addEventListener('click', function (e) { - libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), 'List,Poster,PosterCard,Thumb,ThumbCard'.split(',')); + libraryBrowser.showLayoutMenu(e.target, this.getCurrentViewStyle(), 'List,Poster,PosterCard,Thumb,ThumbCard'.split(',')); }); btnSelectView.addEventListener('layoutchange', function (e) { const viewStyle = e.detail.viewStyle; @@ -256,16 +255,16 @@ import 'emby-itemscontainer'; }); }); }); - } + }; initPage(tabContent); onViewStyleChange(); - self.renderTab = function () { + this.renderTab = function () { reloadItems(tabContent); }; - self.destroy = function () {}; + this.destroy = function () {}; } /* eslint-enable indent */ diff --git a/src/controllers/movies/moviegenres.js b/src/controllers/movies/moviegenres.js index 56fb88b20f..f426ac024d 100644 --- a/src/controllers/movies/moviegenres.js +++ b/src/controllers/movies/moviegenres.js @@ -60,10 +60,10 @@ import 'emby-button'; return enableScrollX() ? 'overflowPortrait' : 'portrait'; } - function fillItemsContainer(entry) { + const fillItemsContainer = (entry) => { const elem = entry.target; const id = elem.getAttribute('data-id'); - const viewStyle = self.getCurrentViewStyle(); + const viewStyle = this.getCurrentViewStyle(); let limit = 'Thumb' == viewStyle || 'ThumbCard' == viewStyle ? 5 : 9; if (enableScrollX()) { @@ -133,7 +133,7 @@ import 'emby-button'; tabContent.querySelector('.btnMoreFromGenre' + id + ' .material-icons').classList.remove('hide'); } }); - } + }; function reloadItems(context, promise) { const query = getQuery(); @@ -189,36 +189,35 @@ import 'emby-button'; }); } - function fullyReload() { - self.preRender(); - self.renderTab(); - } + const fullyReload = () => { + this.preRender(); + this.renderTab(); + }; - const self = this; const data = {}; - self.getViewStyles = function () { + this.getViewStyles = function () { return 'Poster,PosterCard,Thumb,ThumbCard'.split(','); }; - self.getCurrentViewStyle = function () { + this.getCurrentViewStyle = function () { return getPageData().view; }; - self.setCurrentViewStyle = function (viewStyle) { + this.setCurrentViewStyle = function (viewStyle) { getPageData().view = viewStyle; libraryBrowser.saveViewSetting(getSavedQueryKey(), viewStyle); fullyReload(); }; - self.enableViewSelection = true; + this.enableViewSelection = true; let promise; - self.preRender = function () { + this.preRender = function () { promise = getPromise(); }; - self.renderTab = function () { + this.renderTab = function () { reloadItems(tabContent, promise); }; } diff --git a/src/controllers/movies/movies.js b/src/controllers/movies/movies.js index 3b68849036..302e8b717e 100644 --- a/src/controllers/movies/movies.js +++ b/src/controllers/movies/movies.js @@ -297,7 +297,6 @@ import 'emby-itemscontainer'; onViewStyleChange(); }; - //function renderTab () { this.renderTab = function () { itemsContainer.refreshItems(); updateFilterControls(); diff --git a/src/controllers/movies/movietrailers.js b/src/controllers/movies/movietrailers.js index a892769e47..1cab0f1999 100644 --- a/src/controllers/movies/movietrailers.js +++ b/src/controllers/movies/movietrailers.js @@ -54,11 +54,11 @@ import 'emby-itemscontainer'; return context.savedQueryKey; } - function reloadItems() { + const reloadItems = () => { loading.show(); isLoading = true; const query = getQuery(tabContent); - ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { + ApiClient.getItems(ApiClient.getCurrentUserId(), query).then((result) => { function onNextPageClick() { if (isLoading) { return; @@ -94,7 +94,7 @@ import 'emby-itemscontainer'; filterButton: false }); let html; - const viewStyle = self.getCurrentViewStyle(); + const viewStyle = this.getCurrentViewStyle(); if (viewStyle == 'Thumb') { html = cardBuilder.getCardsHtml({ @@ -182,18 +182,17 @@ import 'emby-itemscontainer'; loading.hide(); isLoading = false; }); - } + }; - function updateFilterControls(tabContent) { + const updateFilterControls = (tabContent) => { const query = getQuery(tabContent); - self.alphaPicker.value(query.NameStartsWithOrGreater); - } + this.alphaPicker.value(query.NameStartsWithOrGreater); + }; - const self = this; const data = {}; let isLoading = false; - self.showFilterMenu = function () { + this.showFilterMenu = function () { import('components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => { const filterDialog = new filterDialogFactory({ query: getQuery(tabContent), @@ -208,11 +207,11 @@ import 'emby-itemscontainer'; }); }; - self.getCurrentViewStyle = function () { + this.getCurrentViewStyle = function () { return getPageData(tabContent).view; }; - function initPage(tabContent) { + const initPage = (tabContent) => { const alphaPickerElement = tabContent.querySelector('.alphaPicker'); const itemsContainer = tabContent.querySelector('.itemsContainer'); alphaPickerElement.addEventListener('alphavaluechanged', function (e) { @@ -222,7 +221,7 @@ import 'emby-itemscontainer'; query.StartIndex = 0; reloadItems(); }); - self.alphaPicker = new AlphaPicker({ + this.alphaPicker = new AlphaPicker({ element: alphaPickerElement, valueChangeEvent: 'click' }); @@ -232,7 +231,7 @@ import 'emby-itemscontainer'; itemsContainer.classList.add('padded-right-withalphapicker'); tabContent.querySelector('.btnFilter').addEventListener('click', function () { - self.showFilterMenu(); + this.showFilterMenu(); }); tabContent.querySelector('.btnSort').addEventListener('click', function (e) { libraryBrowser.showSortMenu({ @@ -266,16 +265,16 @@ import 'emby-itemscontainer'; button: e.target }); }); - } + }; initPage(tabContent); - self.renderTab = function () { + this.renderTab = function () { reloadItems(); updateFilterControls(tabContent); }; - self.destroy = function () {}; + this.destroy = function () {}; } /* eslint-enable indent */ From a09ceeefa35e908ac33d29a1cead39fc25b8cb07 Mon Sep 17 00:00:00 2001 From: Cameron Date: Sat, 25 Jul 2020 23:03:15 +0100 Subject: [PATCH 16/56] removal of self --- src/controllers/movies/moviesrecommended.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/controllers/movies/moviesrecommended.js b/src/controllers/movies/moviesrecommended.js index 5e376637b3..dda75a2320 100644 --- a/src/controllers/movies/moviesrecommended.js +++ b/src/controllers/movies/moviesrecommended.js @@ -281,7 +281,7 @@ import 'emby-button'; mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange); } - function getTabController(page, index, callback) { + const getTabController = (page, index, callback) => { let depends = ''; switch (index) { @@ -319,7 +319,7 @@ import 'emby-button'; if (index === suggestionsTabIndex) { tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); - self.tabContent = tabContent; + this.tabContent = tabContent; } let controller = tabControllers[index]; @@ -328,7 +328,7 @@ import 'emby-button'; tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); if (index === suggestionsTabIndex) { - controller = self; + controller = this; } else if (index === 6) { controller = new controllerFactory(view, tabContent, { collectionType: 'movies', @@ -351,7 +351,7 @@ import 'emby-button'; callback(controller); }); - } + }; function preLoadTab(page, index) { getTabController(page, index, function (controller) { @@ -363,12 +363,14 @@ import 'emby-button'; function loadTab(page, index) { currentTabIndex = index; - getTabController(page, index, function (controller) { + getTabController(page, index, ((controller) => { + initialTabIndex = null; + if (renderedTabs.indexOf(index) == -1) { renderedTabs.push(index); controller.renderTab(); } - }); + })); } function onPlaybackStop(e, state) { @@ -390,12 +392,12 @@ import 'emby-button'; var currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)); var suggestionsTabIndex = 1; - self.initTab = function () { + this.initTab = function () { let tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); initSuggestedTab(view, tabContent); }; - self.renderTab = function () { + this.renderTab = function () { let tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); loadSuggestionsTab(view, params, tabContent); }; From f7c3445e1c2c14ebe806e052328ab55432ff15ba Mon Sep 17 00:00:00 2001 From: Cameron Date: Tue, 28 Jul 2020 21:14:40 +0100 Subject: [PATCH 17/56] remove smells --- src/controllers/movies/moviecollections.js | 1 - src/controllers/movies/moviegenres.js | 2 -- src/controllers/movies/movies.js | 1 - src/controllers/movies/moviesrecommended.js | 2 +- src/controllers/movies/movietrailers.js | 1 - 5 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/controllers/movies/moviecollections.js b/src/controllers/movies/moviecollections.js index ffedb10eef..b99c918a13 100644 --- a/src/controllers/movies/moviecollections.js +++ b/src/controllers/movies/moviecollections.js @@ -1,5 +1,4 @@ import loading from 'loading'; -import events from 'events'; import libraryBrowser from 'libraryBrowser'; import imageLoader from 'imageLoader'; import listView from 'listView'; diff --git a/src/controllers/movies/moviegenres.js b/src/controllers/movies/moviegenres.js index f426ac024d..3ca39601fc 100644 --- a/src/controllers/movies/moviegenres.js +++ b/src/controllers/movies/moviegenres.js @@ -3,10 +3,8 @@ import loading from 'loading'; import libraryBrowser from 'libraryBrowser'; import cardBuilder from 'cardBuilder'; import lazyLoader from 'lazyLoader'; -import appHost from 'apphost'; import globalize from 'globalize'; import appRouter from 'appRouter'; -import dom from 'dom'; import 'emby-button'; /* eslint-disable indent */ diff --git a/src/controllers/movies/movies.js b/src/controllers/movies/movies.js index 302e8b717e..91b428ec68 100644 --- a/src/controllers/movies/movies.js +++ b/src/controllers/movies/movies.js @@ -1,5 +1,4 @@ import loading from 'loading'; -import layoutManager from 'layoutManager'; import * as userSettings from 'userSettings'; import events from 'events'; import libraryBrowser from 'libraryBrowser'; diff --git a/src/controllers/movies/moviesrecommended.js b/src/controllers/movies/moviesrecommended.js index dda75a2320..63de12dd35 100644 --- a/src/controllers/movies/moviesrecommended.js +++ b/src/controllers/movies/moviesrecommended.js @@ -423,7 +423,7 @@ import 'emby-button'; events.on(playbackManager, 'playbackstop', onPlaybackStop); inputManager.on(window, onInputCommand); }); - view.addEventListener('viewbeforehide', function (e) { + view.addEventListener('viewbeforehide', function () { inputManager.off(window, onInputCommand); }); for (const tabController of tabControllers) { diff --git a/src/controllers/movies/movietrailers.js b/src/controllers/movies/movietrailers.js index 1cab0f1999..5f1aa1fe62 100644 --- a/src/controllers/movies/movietrailers.js +++ b/src/controllers/movies/movietrailers.js @@ -1,4 +1,3 @@ -import layoutManager from 'layoutManager'; import loading from 'loading'; import events from 'events'; import libraryBrowser from 'libraryBrowser'; From c13742ff544008829398378192143b8726f98085 Mon Sep 17 00:00:00 2001 From: Cameron Date: Wed, 29 Jul 2020 19:23:45 +0100 Subject: [PATCH 18/56] fix lint --- src/controllers/movies/moviesrecommended.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/controllers/movies/moviesrecommended.js b/src/controllers/movies/moviesrecommended.js index 63de12dd35..04f1d26ebf 100644 --- a/src/controllers/movies/moviesrecommended.js +++ b/src/controllers/movies/moviesrecommended.js @@ -388,9 +388,8 @@ import 'emby-button'; } } - var self = this; - var currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)); - var suggestionsTabIndex = 1; + let currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)); + const suggestionsTabIndex = 1; this.initTab = function () { let tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); From 9cafbb3eeb41a60db9719299bd02098c6cfc7190 Mon Sep 17 00:00:00 2001 From: Cameron Date: Thu, 30 Jul 2020 13:32:29 +0100 Subject: [PATCH 19/56] remove duplicates, defaults and fix --- package.json | 6 ++++++ src/controllers/movies/moviesrecommended.js | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 678794aebc..ad4c8e1109 100644 --- a/package.json +++ b/package.json @@ -191,6 +191,12 @@ "src/controllers/music/musicplaylists.js", "src/controllers/music/musicrecommended.js", "src/controllers/music/songs.js", + "src/controllers/dashboard/plugins/repositories.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/dashboard/mediaLibrary.js", "src/controllers/dashboard/metadataImages.js", "src/controllers/dashboard/metadatanfo.js", diff --git a/src/controllers/movies/moviesrecommended.js b/src/controllers/movies/moviesrecommended.js index 04f1d26ebf..ad8579e292 100644 --- a/src/controllers/movies/moviesrecommended.js +++ b/src/controllers/movies/moviesrecommended.js @@ -3,7 +3,7 @@ import layoutManager from 'layoutManager'; import inputManager from 'inputManager'; import * as userSettings from 'userSettings'; import libraryMenu from 'libraryMenu'; -import mainTabsManager from 'mainTabsManager'; +import * as mainTabsManager from 'mainTabsManager'; import cardBuilder from 'cardBuilder'; import dom from 'dom'; import imageLoader from 'imageLoader'; From 9bdc1d8bd9d5b3180fe13d8431c92e9cdda502b1 Mon Sep 17 00:00:00 2001 From: matjaz321 Date: Mon, 3 Aug 2020 21:34:14 +0200 Subject: [PATCH 20/56] Migrated livetvchannels to es6 module --- package.json | 1 + src/controllers/livetv/livetvchannels.js | 241 ++++++++++++----------- 2 files changed, 122 insertions(+), 120 deletions(-) diff --git a/package.json b/package.json index 1d7cf770d3..6540af9f43 100644 --- a/package.json +++ b/package.json @@ -222,6 +222,7 @@ "src/controllers/livetvstatus.js", "src/controllers/livetvguideprovider.js", "src/controllers/livetvsettings.js", + "src/controllers/livetv/livetvchannels.js", "src/controllers/shows/episodes.js", "src/controllers/shows/tvgenres.js", "src/controllers/shows/tvlatest.js", diff --git a/src/controllers/livetv/livetvchannels.js b/src/controllers/livetv/livetvchannels.js index f5a0abeb38..8af6411296 100644 --- a/src/controllers/livetv/livetvchannels.js +++ b/src/controllers/livetv/livetvchannels.js @@ -1,133 +1,134 @@ -define(['cardBuilder', 'imageLoader', 'libraryBrowser', 'loading', 'events', 'userSettings', 'emby-itemscontainer'], function (cardBuilder, imageLoader, libraryBrowser, loading, events, userSettings) { - 'use strict'; +import cardBuilder from 'cardBuilder'; +import imageLoader from 'imageLoader'; +import libraryBrowser from 'libraryBrowser'; +import loading from 'loading'; +import events from 'events'; +import userSettings from 'userSettings'; +import 'emby-itemscontainer'; - loading = loading.default || loading; - libraryBrowser = libraryBrowser.default || libraryBrowser; +export default function (view, params, tabContent) { + function getPageData() { + if (!pageData) { + pageData = { + query: { + StartIndex: 0, + Fields: 'PrimaryImageAspectRatio' + } + }; + } - return function (view, params, tabContent) { - function getPageData() { - if (!pageData) { - pageData = { - query: { - StartIndex: 0, - Fields: 'PrimaryImageAspectRatio' - } - }; + if (userSettings.libraryPageSize() > 0) { + pageData.query['Limit'] = userSettings.libraryPageSize(); + } + + return pageData; + } + + function getQuery() { + return getPageData().query; + } + + function getChannelsHtml(channels) { + return cardBuilder.getCardsHtml({ + items: channels, + shape: 'square', + showTitle: true, + lazy: true, + cardLayout: true, + showDetailsMenu: true, + showCurrentProgram: true, + showCurrentProgramTime: true + }); + } + + function renderChannels(context, result) { + function onNextPageClick() { + if (isLoading) { + return; } if (userSettings.libraryPageSize() > 0) { - pageData.query['Limit'] = userSettings.libraryPageSize(); + query.StartIndex += query.Limit; + } + reloadItems(context); + } + + function onPreviousPageClick() { + if (isLoading) { + return; } - return pageData; - } - - function getQuery() { - return getPageData().query; - } - - function getChannelsHtml(channels) { - return cardBuilder.getCardsHtml({ - items: channels, - shape: 'square', - showTitle: true, - lazy: true, - cardLayout: true, - showDetailsMenu: true, - showCurrentProgram: true, - showCurrentProgramTime: true - }); - } - - function renderChannels(context, result) { - function onNextPageClick() { - if (isLoading) { - return; - } - - if (userSettings.libraryPageSize() > 0) { - query.StartIndex += query.Limit; - } - reloadItems(context); - } - - function onPreviousPageClick() { - if (isLoading) { - return; - } - - if (userSettings.libraryPageSize() > 0) { - query.StartIndex = Math.max(0, query.StartIndex - query.Limit); - } - reloadItems(context); - } - - var query = getQuery(); - context.querySelector('.paging').innerHTML = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: false, - updatePageSizeSetting: false, - filterButton: false - }); - var html = getChannelsHtml(result.Items); - var elem = context.querySelector('#items'); - elem.innerHTML = html; - imageLoader.lazyChildren(elem); - var i; - var length; - var elems; - - for (elems = context.querySelectorAll('.btnNextPage'), i = 0, length = elems.length; i < length; i++) { - elems[i].addEventListener('click', onNextPageClick); - } - - for (elems = context.querySelectorAll('.btnPreviousPage'), i = 0, length = elems.length; i < length; i++) { - elems[i].addEventListener('click', onPreviousPageClick); + if (userSettings.libraryPageSize() > 0) { + query.StartIndex = Math.max(0, query.StartIndex - query.Limit); } + reloadItems(context); } - function showFilterMenu(context) { - require(['components/filterdialog/filterdialog'], function ({default: filterDialogFactory}) { - var filterDialog = new filterDialogFactory({ - query: getQuery(), - mode: 'livetvchannels', - serverId: ApiClient.serverId() - }); - events.on(filterDialog, 'filterchange', function () { - reloadItems(context); - }); - filterDialog.show(); - }); - } - - function reloadItems(context, save) { - loading.show(); - isLoading = true; - var query = getQuery(); - var apiClient = ApiClient; - query.UserId = apiClient.getCurrentUserId(); - apiClient.getLiveTvChannels(query).then(function (result) { - renderChannels(context, result); - loading.hide(); - isLoading = false; - - require(['autoFocuser'], function (autoFocuser) { - autoFocuser.autoFocus(view); - }); - }); - } - - var pageData; - var self = this; - var isLoading = false; - tabContent.querySelector('.btnFilter').addEventListener('click', function () { - showFilterMenu(tabContent); + const query = getQuery(); + context.querySelector('.paging').innerHTML = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + filterButton: false }); + const html = getChannelsHtml(result.Items); + const elem = context.querySelector('#items'); + elem.innerHTML = html; + imageLoader.lazyChildren(elem); + let i; + let length; + let elems; - self.renderTab = function () { - reloadItems(tabContent); - }; + for (elems = context.querySelectorAll('.btnNextPage'), i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener('click', onNextPageClick); + } + + for (elems = context.querySelectorAll('.btnPreviousPage'), i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener('click', onPreviousPageClick); + } + } + + function showFilterMenu(context) { + import(['components/filterdialog/filterdialog']).then(({default: filterDialogFactory}) => { + const filterDialog = new filterDialogFactory({ + query: getQuery(), + mode: 'livetvchannels', + serverId: ApiClient.serverId() + }); + events.on(filterDialog, 'filterchange', function () { + reloadItems(context); + }); + filterDialog.show(); + }); + } + + function reloadItems(context, save) { + loading.show(); + isLoading = true; + const query = getQuery(); + const apiClient = ApiClient; + query.UserId = apiClient.getCurrentUserId(); + apiClient.getLiveTvChannels(query).then(function (result) { + renderChannels(context, result); + loading.hide(); + isLoading = false; + + require(['autoFocuser'], function (autoFocuser) { + autoFocuser.autoFocus(view); + }); + }); + } + + let pageData; + const self = this; + let isLoading = false; + tabContent.querySelector('.btnFilter').addEventListener('click', function () { + showFilterMenu(tabContent); + }); + + self.renderTab = function () { + reloadItems(tabContent); }; -}); +} From ddf364adb2e08443d79092810d0b3096243c1645 Mon Sep 17 00:00:00 2001 From: Cameron Date: Mon, 3 Aug 2020 20:46:39 +0100 Subject: [PATCH 21/56] Lint --- src/controllers/movies/moviegenres.js | 4 ++-- src/controllers/movies/moviesrecommended.js | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/controllers/movies/moviegenres.js b/src/controllers/movies/moviegenres.js index 3ca39601fc..ca02ede36d 100644 --- a/src/controllers/movies/moviegenres.js +++ b/src/controllers/movies/moviegenres.js @@ -62,13 +62,13 @@ import 'emby-button'; const elem = entry.target; const id = elem.getAttribute('data-id'); const viewStyle = this.getCurrentViewStyle(); - let limit = 'Thumb' == viewStyle || 'ThumbCard' == viewStyle ? 5 : 9; + let limit = viewStyle == 'Thumb' || viewStyle == 'ThumbCard' ? 5 : 9; if (enableScrollX()) { limit = 10; } - const enableImageTypes = 'Thumb' == viewStyle || 'ThumbCard' == viewStyle ? 'Primary,Backdrop,Thumb' : 'Primary'; + const enableImageTypes = viewStyle == 'Thumb' || viewStyle == 'ThumbCard' ? 'Primary,Backdrop,Thumb' : 'Primary'; const query = { SortBy: 'SortName', SortOrder: 'Ascending', diff --git a/src/controllers/movies/moviesrecommended.js b/src/controllers/movies/moviesrecommended.js index ad8579e292..5cba66d2f8 100644 --- a/src/controllers/movies/moviesrecommended.js +++ b/src/controllers/movies/moviesrecommended.js @@ -16,8 +16,6 @@ import 'emby-button'; /* eslint-disable indent */ - playbackManager = playbackManager.default || playbackManager; - function enableScrollX() { return !layoutManager.desktop; } @@ -364,8 +362,6 @@ import 'emby-button'; function loadTab(page, index) { currentTabIndex = index; getTabController(page, index, ((controller) => { - initialTabIndex = null; - if (renderedTabs.indexOf(index) == -1) { renderedTabs.push(index); controller.renderTab(); From 4b84e6c0aa97d53be1996941591c762126251116 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Tue, 4 Aug 2020 00:51:19 +0300 Subject: [PATCH 22/56] Fix old Edge loading --- src/scripts/site.js | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 604f9c7bab..ab8e17971d 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -696,20 +696,12 @@ function initClient() { onError: onRequireJsError }); - require(['fetch']); - require(['polyfill']); - require(['fast-text-encoding']); - require(['intersection-observer']); - require(['classlist-polyfill']); - - // Expose jQuery globally - require(['jQuery'], function(jQuery) { - window.$ = jQuery; - window.jQuery = jQuery; - }); - - require(['css!assets/css/site']); - require(['jellyfin-noto']); + require(['fetch']) + .then(() => require(['jQuery', 'polyfill', 'fast-text-encoding', 'intersection-observer', 'classlist-polyfill', 'css!assets/css/site', 'jellyfin-noto'], (jQuery) => { + // Expose jQuery globally + window.$ = jQuery; + window.jQuery = jQuery; + })); // define styles // TODO determine which of these files can be moved to the components themselves From 07a54e93039593b9f66769951f6aa34d044528e8 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Tue, 4 Aug 2020 09:39:34 +0300 Subject: [PATCH 23/56] Wait for initialization to complete --- src/scripts/site.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index ab8e17971d..cd85c35e83 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -615,6 +615,7 @@ function initClient() { } var localApiClient; + let promise; (function () { var urlArgs = 'v=' + (window.dashboardVersion || new Date().getDate()); @@ -696,7 +697,7 @@ function initClient() { onError: onRequireJsError }); - require(['fetch']) + promise = require(['fetch']) .then(() => require(['jQuery', 'polyfill', 'fast-text-encoding', 'intersection-observer', 'classlist-polyfill', 'css!assets/css/site', 'jellyfin-noto'], (jQuery) => { // Expose jQuery globally window.$ = jQuery; @@ -1107,7 +1108,7 @@ function initClient() { }); })(); - return onWebComponentsReady(); + promise.then(onWebComponentsReady); } initClient(); From 70204584274b831e6ac9c5187c258cf355c1272a Mon Sep 17 00:00:00 2001 From: Matjaz Zavski Date: Tue, 4 Aug 2020 12:59:21 +0200 Subject: [PATCH 24/56] Update src/controllers/livetv/livetvchannels.js Co-authored-by: Cameron --- src/controllers/livetv/livetvchannels.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/livetv/livetvchannels.js b/src/controllers/livetv/livetvchannels.js index 8af6411296..14d7bcfdf4 100644 --- a/src/controllers/livetv/livetvchannels.js +++ b/src/controllers/livetv/livetvchannels.js @@ -3,7 +3,7 @@ import imageLoader from 'imageLoader'; import libraryBrowser from 'libraryBrowser'; import loading from 'loading'; import events from 'events'; -import userSettings from 'userSettings'; +import * as userSettings from 'userSettings'; import 'emby-itemscontainer'; export default function (view, params, tabContent) { From e3fe8a1964acfd7acdb154ffbe4b10d80ccf4f3c Mon Sep 17 00:00:00 2001 From: Matjaz Zavski Date: Tue, 4 Aug 2020 12:59:28 +0200 Subject: [PATCH 25/56] Update src/controllers/livetv/livetvchannels.js Co-authored-by: Cameron --- src/controllers/livetv/livetvchannels.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/livetv/livetvchannels.js b/src/controllers/livetv/livetvchannels.js index 14d7bcfdf4..7cdddda716 100644 --- a/src/controllers/livetv/livetvchannels.js +++ b/src/controllers/livetv/livetvchannels.js @@ -115,7 +115,7 @@ export default function (view, params, tabContent) { loading.hide(); isLoading = false; - require(['autoFocuser'], function (autoFocuser) { + import('autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(view); }); }); From a54d8338a8b30dc0f6eec1530858ddf124d97822 Mon Sep 17 00:00:00 2001 From: SaddFox Date: Tue, 4 Aug 2020 09:43:10 +0000 Subject: [PATCH 26/56] Translated using Weblate (Slovenian) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/sl/ --- src/strings/sl-si.json | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/strings/sl-si.json b/src/strings/sl-si.json index a8f3bd020c..066254a3dd 100644 --- a/src/strings/sl-si.json +++ b/src/strings/sl-si.json @@ -785,7 +785,7 @@ "MessagePlayAccessRestricted": "Predvajanje te vsebine je trenutno omejeno. Za več informacij se obrnite na skrbnika strežnika.", "NoSubtitlesHelp": "Podnapisi se privzeto ne bodo naložili. Med predvajanjem jih lahko še vedno ročno vklopite.", "MessagePluginConfigurationRequiresLocalAccess": "Za nastavitev tega dodatka se prosimo prijavite neposredno na vaš lokalni strežnik.", - "OptionAllowMediaPlaybackTranscodingHelp": "Omejitev dostopa do prekodiranja lahko povzroči napake pri predvajanju v Jellyfin aplikacijah zaradi nepodprtih formatov predstavnosti.", + "OptionAllowMediaPlaybackTranscodingHelp": "Omejitev dostopa do prekodiranja lahko povzroči napake pri predvajanju v odjemalcih zaradi nepodprtih formatov predstavnosti.", "OptionAllowVideoPlaybackRemuxing": "Dovoli predvajanje videoposnetkov, ki zahtevajo pretvarjanje brez prekodiranja", "ViewPlaybackInfo": "Oglejte si informacije o predvajanju", "WizardCompleted": "To je vse kar potrebujemo za zdaj. Jellyfin je začel zbirati informacije o vaši knjižnici predstavnosti. Oglejte si nekaj naših aplikacij in nato kliknite Zaključi za ogled Nadzorne plošče.", @@ -886,7 +886,7 @@ "MediaInfoExternal": "Zunanji", "Refresh": "Osveži", "MetadataManager": "Upravitelj metapodatkov", - "MetadataSettingChangeHelp": "Spreminjanje nastavitev metapodatkov bo vplivalo na nove vsebine. Za osvežitev obstoječih vsebin, odprite okno s podrobnostmi in kliknite gumb Osveži, ali množično osvežite metapodatke z upraviteljem metapodatkov.", + "MetadataSettingChangeHelp": "Spreminjanje nastavitev metapodatkov bo vplivalo na novo dodane vsebine. Za osvežitev obstoječih vsebin, odprite okno s podrobnostmi in kliknite gumb Osveži, ali množično osvežite metapodatke z upraviteljem metapodatkov.", "RefreshMetadata": "Osveži metapodatke", "RefreshQueued": "Osvežitev v čakalni vrsti.", "Shuffle": "Premešaj", @@ -940,7 +940,7 @@ "MessagePleaseWait": "Prosimo, počakajte. To lahko traja nekaj minut.", "MessagePleaseEnsureInternetMetadata": "Prosimo poskrbite, da je prenašanje spletnih metapodatkov omogočeno.", "MessageNothingHere": "Tu ni nič.", - "MessageNoTrailersFound": "Napovednikov ni bilo mogoče najti. Namestite kanal napovednikov in izboljšajte svojo filmsko izkušnjo s knjižnico spletnih napovednikov.", + "MessageNoTrailersFound": "Namestite kanal napovednikov in izboljšajte svojo knjižnico z dodajanjem spletnih napovednikov.", "MessageNoServersAvailable": "Z samodejnim odkrivanjem strežnikov ni bilo mogoče najti nobenega strežnika.", "MessageNoPluginsInstalled": "Nameščenih nimate nobenih dodatkov.", "MessageNoAvailablePlugins": "Dodatki niso na voljo.", @@ -981,7 +981,7 @@ "MediaInfoResolution": "Ločljivost", "MediaInfoRefFrames": "Ref sličice", "MediaInfoProfile": "Profil", - "MediaInfoPixelFormat": "Format pik", + "MediaInfoPixelFormat": "Format pikslov", "MediaInfoPath": "Pot", "MediaInfoLevel": "Stopnja", "MediaInfoInterlaced": "Prepleteno", @@ -1377,5 +1377,30 @@ "TabNotifications": "Obvestila", "TabNfoSettings": "Nastavitve NFO", "TabMusicVideos": "Videospoti", - "TabMovies": "Filmi" + "TabMovies": "Filmi", + "OptionForceRemoteSourceTranscoding": "Vsili prekodiranje oddaljenih virov predstavnosti (na primer TV v živo)", + "Off": "Izključeno", + "Normal": "Normalno", + "NoSubtitleSearchResultsFound": "Ni zadetkov.", + "MessageNoNextUpItems": "Ničesar ni bilo mogoče najti. Začnite gledati vaše serije!", + "NoCreatedLibraries": "Izgleda da niste dodali še nobene knjižnice. {0}Želite dodati eno zdaj?{1}", + "NextTrack": "Preskoči na naslednjo", + "TvLibraryHelp": "Preglejte {0}napotke za poimenovanje serij{1}.", + "MusicLibraryHelp": "Preglejte {0}napotke za poimenovanje glasbe{1}.", + "MovieLibraryHelp": "Preglejte {0}napotke za poimenovanje filmov{1}.", + "MoreMediaInfo": "Informacije o predstavnosti", + "Mobile": "Telefon", + "MessageSyncPlayErrorMedia": "Aktivacija SyncPlay ni uspela! Napaka predstavnosti.", + "MessageSyncPlayErrorMissingSession": "Aktivacija SyncPlay ni uspela! Manjka seja.", + "MessageSyncPlayErrorNoActivePlayer": "Najdeno ni bilo nobeno aktivno predvajanje. SyncPlay je bil onemogočen.", + "MessageSyncPlayErrorAccessingGroups": "Pri dostopu do seznama skupin je prišlo do napake.", + "MessageSyncPlayJoinGroupDenied": "Za uporabo SyncPlay je potrebno dovoljenje.", + "MessageSyncPlayGroupDoesNotExist": "Pridružitev skupini ni bila uspešna, ker ta ne obstaja.", + "MessageSyncPlayNoGroupsAvailable": "Na voljo ni nobene skupine. Začnite gledati nekaj.", + "MessageSyncPlayDisabled": "SyncPlay onemogočen.", + "MessageSyncPlayEnabled": "SyncPlay omogočen.", + "MessageUnsetContentHelp": "Vsebine bodo prikazane kot preproste mape. Za najboljše rezultate uporabite upravitelj metapodatkov in nastavite vrsto vsebin podmap.", + "MessageLeaveEmptyToInherit": "Pustite prazno za podedovanje nastavitev od nadrejenega elementa ali globalne privzete vrednosti.", + "LabelXDlnaDocHelp": "Določa vsebino X_DLNADOC elementa v urn:schemas-dlna-org:device-1-0 namespace.", + "LabelXDlnaCapHelp": "Določa vsebino X_DLNACAP elementa v urn:schemas-dlna-org:device-1-0 namespace." } From 39a5a76be1ab4c2110bfba0979bad93d1756a4a8 Mon Sep 17 00:00:00 2001 From: SaddFox Date: Tue, 4 Aug 2020 11:15:34 +0000 Subject: [PATCH 27/56] Translated using Weblate (Slovenian) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/sl/ --- src/strings/sl-si.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/strings/sl-si.json b/src/strings/sl-si.json index 066254a3dd..2f08ad8b40 100644 --- a/src/strings/sl-si.json +++ b/src/strings/sl-si.json @@ -910,7 +910,7 @@ "LabelPasswordResetProvider": "Ponudnik ponastavitve gesla:", "LabelPasswordConfirm": "Potrditev gesla:", "LabelPassword": "Geslo:", - "OptionDisableUserHelp": "Če onemogočite strežnik ne bo dovolil povezav od tega uporabnika. Obstoječe povezave bodo prekinjene.", + "OptionDisableUserHelp": "Strežnik ne bo dovolil nobenih povezav od tega uporabnika. Obstoječe povezave bodo prekinjene.", "OptionDescending": "Padajoče", "OptionDatePlayed": "Datum predvajanja", "OptionDateAddedImportTime": "Uporabi datum dodajanja v knjižnico", @@ -929,7 +929,7 @@ "OptionBlockMovies": "Filmi", "OptionBlockBooks": "Knjige", "OptionBanner": "Pasica", - "OptionAutomaticallyGroupSeriesHelp": "Če je omogočeno, bodo serije, ki so razdeljene v več mapah znotraj knjižnice samodejno združene v eno serijo.", + "OptionAutomaticallyGroupSeriesHelp": "Serije, ki so razdeljene v več mapah znotraj knjižnice bodo samodejno združene v eno serijo.", "OptionAutomaticallyGroupSeries": "Samodejno združi serije, ki so razdeljene po več mapah", "OptionAscending": "Naraščajoče", "OptionArtist": "Izvajalec", @@ -1402,5 +1402,6 @@ "MessageUnsetContentHelp": "Vsebine bodo prikazane kot preproste mape. Za najboljše rezultate uporabite upravitelj metapodatkov in nastavite vrsto vsebin podmap.", "MessageLeaveEmptyToInherit": "Pustite prazno za podedovanje nastavitev od nadrejenega elementa ali globalne privzete vrednosti.", "LabelXDlnaDocHelp": "Določa vsebino X_DLNADOC elementa v urn:schemas-dlna-org:device-1-0 namespace.", - "LabelXDlnaCapHelp": "Določa vsebino X_DLNACAP elementa v urn:schemas-dlna-org:device-1-0 namespace." + "LabelXDlnaCapHelp": "Določa vsebino X_DLNACAP elementa v urn:schemas-dlna-org:device-1-0 namespace.", + "OptionDislikes": "Ni mi všeč" } From 39a003742716d7dcfe7e27e232fea91743f722d3 Mon Sep 17 00:00:00 2001 From: Matjaz Zavski Date: Tue, 4 Aug 2020 14:12:43 +0200 Subject: [PATCH 28/56] Update src/controllers/livetv/livetvchannels.js Co-authored-by: Cameron --- src/controllers/livetv/livetvchannels.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/livetv/livetvchannels.js b/src/controllers/livetv/livetvchannels.js index 7cdddda716..d34fe58132 100644 --- a/src/controllers/livetv/livetvchannels.js +++ b/src/controllers/livetv/livetvchannels.js @@ -115,7 +115,7 @@ export default function (view, params, tabContent) { loading.hide(); isLoading = false; - import('autoFocuser').then(({default: autoFocuser}) => { + import('autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(view); }); }); From ce8484e8f0c37678b0cf1dbd1d84c8e1dc85fd2b Mon Sep 17 00:00:00 2001 From: SaddFox Date: Tue, 4 Aug 2020 12:55:59 +0000 Subject: [PATCH 29/56] Translated using Weblate (Slovenian) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/sl/ --- src/strings/sl-si.json | 52 +++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/src/strings/sl-si.json b/src/strings/sl-si.json index 2f08ad8b40..423ee7797c 100644 --- a/src/strings/sl-si.json +++ b/src/strings/sl-si.json @@ -448,7 +448,7 @@ "FastForward": "Hitro naprej", "FFmpegSavePathNotFound": "Nismo mogli locirati FFmpeg na navedeni poti. FFprobe je prav tako zahtevan in mora biti v isti mapi. Ti komponenti sta običajno združeni skupaj v istem prenosu. Preverite pot in poskusite znova.", "Extras": "Dodatki", - "ExtractChapterImagesHelp": "Izločanje slik poglavij omogoča odjemalcem prikaz grafičnih menijev za izbor scene. Ta proces je lahko počasen, procesorsko zahteven in lahko potrebuje več gigabajtov prostora na disku. Teče ob odkritju novih videov in kot načrtovana naloga ponoči. Urnik izvajanja lahko nastavite v nastavitvah načrtovanih nalog. Zaganjanje tega procesa med urami visoke obremenitve ni priporočeno.", + "ExtractChapterImagesHelp": "Ekstrakcija slik poglavij omogoča odjemalcem prikaz grafičnih menijev za izbor scene. Ta proces je lahko počasen, procesorsko zahteven in lahko potrebuje več gigabajtov prostora na disku. Teče ob odkritju novih videov in kot načrtovana naloga ponoči. Urnik izvajanja lahko nastavite v nastavitvah načrtovanih nalog. Zaganjanje tega procesa med urami visoke obremenitve ni priporočeno.", "ExtraLarge": "Zelo veliko", "ExitFullscreen": "Izhod in celozaslonskega načina", "ErrorSavingTvProvider": "Prišlo je do težave pri shranjevanju TV ponudnika. Preverite ali je dostopen in poskusite znova.", @@ -723,16 +723,16 @@ "LabelMonitorUsers": "Spremljaj aktivnost iz:", "LabelMovieCategories": "Kategorije filmov:", "LabelMoviePrefix": "Predpona filma:", - "LabelMovieRecordingPath": "Pot za snemanje filmov (neobvezno):", + "LabelMovieRecordingPath": "Pot za snemanje filmov:", "LabelMusicStreamingTranscodingBitrate": "Bitna hitrost pretvarjanja glasbe:", - "LabelMusicStreamingTranscodingBitrateHelp": "Določi največjo bitno hitrost pretakanja glasbe.", + "LabelMusicStreamingTranscodingBitrateHelp": "Določite največjo bitno hitrost pretakanja glasbe.", "LabelName": "Ime:", "LabelFriendlyName": "Uporabniku prijazno ime:", "LabelKodiMetadataEnablePathSubstitutionHelp": "Omogoči zamenjavo poti za poti slik glede na nastavitve zamenjave poti strežnika.", "LabelKodiMetadataSaveImagePaths": "Shrani poti slik znotraj nfo datotek", "LabelMetadataDownloadersHelp": "Omogoči in uredi želene vire metapodatkov po prioriteti. Viri z nižjo prioriteto bodo uporabljeni zgolj za dopolnjevanje manjkajočih informacij.", "LabelBaseUrlHelp": "Dodjte podnaslov po meri na konec URL-ja strežnika. Na primer: http://example.com/<baseurl>", - "LabelExtractChaptersDuringLibraryScanHelp": "Ustvari slike poglavij med uvozom videov pri preiskovanju knjižnjice. Sicer bodo ustvarjene med načrtovanim opravilom, kar omogoča hitrejše preiskovanje knjižnjice.", + "LabelExtractChaptersDuringLibraryScanHelp": "Ustvari slike poglavij med uvozom videov pri preiskovanju knjižnjice. Sicer bodo ustvarjene med načrtovanim opravilom ekstrakcije slik, kar omogoča hitrejše preiskovanje knjižnjice.", "LabelForgotPasswordUsernameHelp": "Vpišite svoje uporabniško ime, v kolikor se ga spomnite.", "LabelInNetworkSignInWithEasyPasswordHelp": "Uporabi enostavno PIN kodo za prijavo v naprave znotraj lokalnega omrežja. Vaše geslo bo potrebno zgolj za prijave zunaj domačega omrežja. Če pustite prazno, za prijavo v domačem omrežju omrežju ne boste potrebovali gesla.", "LabelMaxStreamingBitrate": "Največja kvaliteta pretakanja:", @@ -820,7 +820,7 @@ "OptionReportByteRangeSeekingWhenTranscoding": "Sporoči, da strežnik podpira iskanje po bajtih pri prekodiranju", "Quality": "Kvaliteta", "PlaceFavoriteChannelsAtBeginning": "Postavi priljubljene kanale na začetek", - "LabelOptionalNetworkPath": "(Neobvezno) Omrežna mapa:", + "LabelOptionalNetworkPath": "Omrežna mapa v skupni rabi:", "LabelOptionalNetworkPathHelp": "V primeru, da je mapa deljena v vašem omrežju, lahko Jellyfin deli omrežno pot z ostalimi napravami in jim omogoči neposreden dostop do vsebin. Na primer {0} ali {1}.", "LabelRemoteClientBitrateLimitHelp": "Neobvezna omejitev bitne hitrosti na posamezno predvajanje za vse naprave izven domačega omrežja. S tem lahko preprečite, da bi naprave zahtevale višjo bitno hitrost predvajanja, kot jo lahko prenese vaše omrežje. To lahko poveča obremenitev CPU-ja, saj bo morda potrebno sprotno prekodiranje za zmanjšanje bitne hitrosti.", "LanNetworksHelp": "Z vejico ločen seznam IP naslovov ali IP/maska omrežji, ki bodo upoštevana kot lokalna pri uveljavljanju omejitev pasovne širine. Če nastavite, se bodo vsi ostali naslovi upoštevali kot zunanji in bodo predmet omejitve pasovne širine. Če pustite prazno, bo kot lokalno omrežje upoštevano zgolj omrežje strežnika.", @@ -848,14 +848,14 @@ "OptionWeekly": "Tedensko", "OriginalAirDateValue": "Prvotni datum predvajanja: {0}", "Overview": "Pregled", - "PackageInstallCancelled": "{0} namestitev preklicana.", - "PackageInstallCompleted": "{0} namestitev uspešna.", - "PackageInstallFailed": "{0} namestitev neuspešna.", + "PackageInstallCancelled": "{0} (različica {1}) namestitev preklicana.", + "PackageInstallCompleted": "{0} (različica {1}) namestitev uspešna.", + "PackageInstallFailed": "{0} (različica {1}) namestitev neuspešna.", "PasswordMatchError": "Geslo in potrditev gesla se moreta ujemati.", "PasswordResetComplete": "Geslo je bilo ponastavljeno.", "PasswordResetConfirmation": "Ali ste prepričani, da želite ponastaviti geslo?", "HeaderResetPassword": "Ponastavi geslo", - "PasswordResetProviderHelp": "Izberite ponudnika ponastavitve gesla, ki bo uporabljen, ko bo ta uporabnik zahteval ponastavitev gesla", + "PasswordResetProviderHelp": "Izberite ponudnika ponastavitve gesla, ki bo uporabljen, ko bo ta uporabnik zahteval ponastavitev gesla.", "PasswordSaved": "Geslo shranjeno.", "PerfectMatch": "Popolno ujemanje", "PictureInPicture": "Slika v sliki", @@ -1047,7 +1047,7 @@ "OptionDvd": "DVD", "OptionDownloadMenuImage": "Meni", "OptionDownloadLogoImage": "Logotip", - "OptionDownloadImagesInAdvanceHelp": "Privzeto se večina slik prenese šele, ko jih zahtevajo aplikacije. Omogočite to možnost za prenos slik vnaprej, pri uvozu predstavnosti. To lahko občutno podaljša preiskovanje knjižnice.", + "OptionDownloadImagesInAdvanceHelp": "Privzeto se večina slik prenese šele, ko jih zahtevajo odjemalci. Omogočite to možnost za prenos slik vnaprej, pri uvozu predstavnosti. To lahko občutno podaljša preiskovanje knjižnic.", "OptionDownloadImagesInAdvance": "Prenesi slike vnaprej", "OptionAllowSyncTranscoding": "Dovoli prenašanje in sinhronizacijo predstavnosti ki zahteva pretvarjanje", "OptionAllowRemoteControlOthers": "Dovoli daljinsko upravljanje drugih uporabnikov", @@ -1077,14 +1077,14 @@ "LabelServerName": "Ime strežnika:", "LabelServerHostHelp": "192.168.1.100:8096 ali https://myserver.com", "LabelServerHost": "Naslov:", - "LabelSeriesRecordingPath": "Pot za snemanje serij (neobvezno):", + "LabelSeriesRecordingPath": "Pot za snemanje serij:", "LabelSerialNumber": "Serijska številka", "LabelSendNotificationToUsers": "Pošlji obvestilo na:", "LabelSeasonNumber": "Številka sezone:", "LabelScreensaver": "Ohranjevalnik zaslona:", "LabelSaveLocalMetadataHelp": "Shranjevanje slik v mape predstavnosti omogoča lažji dostop in urejanje slik.", "LabelSaveLocalMetadata": "Shrani slike v mape predstavnosti", - "LabelRuntimeMinutes": "Čas trajanja (minute):", + "LabelRuntimeMinutes": "Čas trajanja:", "LabelRemoteClientBitrateLimit": "Omejitev bitne hitrosti pretakanja preko interneta (Mbps):", "LabelRecordingPathHelp": "Določite privzeto lokacijo za shranjevanje posnetkov. Če pustite prazno, bo uporabljena mapa namestitve strežnika.", "LabelRecordingPath": "Privzeta pot posnetkov:", @@ -1403,5 +1403,31 @@ "MessageLeaveEmptyToInherit": "Pustite prazno za podedovanje nastavitev od nadrejenega elementa ali globalne privzete vrednosti.", "LabelXDlnaDocHelp": "Določa vsebino X_DLNADOC elementa v urn:schemas-dlna-org:device-1-0 namespace.", "LabelXDlnaCapHelp": "Določa vsebino X_DLNACAP elementa v urn:schemas-dlna-org:device-1-0 namespace.", - "OptionDislikes": "Ni mi všeč" + "OptionDislikes": "Ni mi všeč", + "ClearQueue": "Počisti čakalno vrsto", + "StopPlayback": "Ustavi predvajanje", + "ButtonCast": "Zasedba", + "EnableBlurHashHelp": "Med nalaganjem bodo slike nadomeščene z edinstvenimi nadomestnimi sličicami.", + "EnableBlurHash": "Omogoči zamegljene začasne sličice za slike", + "UnsupportedPlayback": "Jellyfin ne more dešifrirati vsebin zaščitenih z DRM, vendar bo strežnik kljub temu poskušal predvajati vse vsebine. Zaradi šifriranja ali drugih nepodprtih funkcij, na primer interaktivnih naslovov, bodo nekatere vsebine prikazane popolnoma črne.", + "OnApplicationStartup": "Ob zagonu aplikacije", + "EveryXHours": "Vsakih {0} ur", + "EveryHour": "Vsako uro", + "EveryXMinutes": "Vsakih {0} minut", + "OnWakeFromSleep": "Ob prebujenju iz spanja", + "WeeklyAt": "{0}s ob {1}", + "DailyAt": "Vsak dan ob {0}", + "OptionPlainVideoItemsHelp": "Vsi videi so predstavljeni v DIDL kot \"object.item.videoItem\" namesto bolj specifičen tip, kot na primer \"object.item.videoItem.movie\".", + "OptionPlainVideoItems": "Prikaži vse videe kot preproste video vsebine", + "OptionPlainStorageFoldersHelp": "Vse mape so predstavljene v DIDL kot \"object.container.storageFolder\" namesto bolj specifičen tip, kot na primer \"object.container.person.musicArtist\".", + "OptionPlainStorageFolders": "Prikaži vse mape kot enostavne mape shrambe", + "OptionHlsSegmentedSubtitles": "HLS ločeni podnapisi", + "OptionExtractChapterImage": "Omogoči ekstrakcijo slik poglavij", + "OptionEstimateContentLength": "Oceni dolžino vsebine pri prekodiranju", + "OptionEquals": "Je enako", + "OptionEnded": "Zaključeno", + "OptionEnableM2tsModeHelp": "Omogoči m2ts način pri kodiranju v mpegts.", + "OptionEnableM2tsMode": "Omogoči M2ts način", + "OptionDisplayFolderViewHelp": "Prikaže mape poleg ostalih knjižnic predstavnosti. Uporabno za preprost ogled map.", + "OptionDisplayFolderView": "Prikaži pogled mape za prikaz navadnih map predstavnosti" } From 4b1e94867ced840b2df1934924fe36bf4c92c248 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2020 16:47:34 +0000 Subject: [PATCH 30/56] Bump whatwg-fetch from 3.2.0 to 3.3.1 Bumps [whatwg-fetch](https://github.com/github/fetch) from 3.2.0 to 3.3.1. - [Release notes](https://github.com/github/fetch/releases) - [Commits](https://github.com/github/fetch/compare/v3.2.0...v3.3.1) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 1d7cf770d3..7365d4f0e4 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "sortablejs": "^1.10.2", "swiper": "^5.4.5", "webcomponents.js": "^0.7.24", - "whatwg-fetch": "^3.2.0" + "whatwg-fetch": "^3.3.1" }, "babel": { "presets": [ diff --git a/yarn.lock b/yarn.lock index 17c2b176ef..400a7c2bee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11988,10 +11988,10 @@ webworkify@^1.5.0: resolved "https://registry.yarnpkg.com/webworkify/-/webworkify-1.5.0.tgz#734ad87a774de6ebdd546e1d3e027da5b8f4a42c" integrity sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g== -whatwg-fetch@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.2.0.tgz#8e134f701f0a4ab5fda82626f113e2b647fd16dc" - integrity sha512-SdGPoQMMnzVYThUbSrEvqTlkvC1Ux27NehaJ/GUHBfNrh5Mjg+1/uRyFMwVnxO2MrikMWvWAqUGgQOfVU4hT7w== +whatwg-fetch@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.3.1.tgz#6c1acf37dec176b0fd6bc9a74b616bec2f612935" + integrity sha512-faXTmGDcLuEPBpJwb5LQfyxvubKiE+RlbmmweFGKjvIPFj4uHTTfdtTIkdTRhC6OSH9S9eyYbx8kZ0UEaQqYTA== which-module@^1.0.0: version "1.0.0" From a930482ca11df112e7eac1b1a57d36a588331195 Mon Sep 17 00:00:00 2001 From: matjaz321 Date: Tue, 4 Aug 2020 19:00:19 +0200 Subject: [PATCH 31/56] Fixed linting errors --- src/controllers/dashboard/notifications/notifications/index.js | 1 - src/controllers/livetv/livetvrecordings.js | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/controllers/dashboard/notifications/notifications/index.js b/src/controllers/dashboard/notifications/notifications/index.js index d12a5f2e61..b97403f8eb 100644 --- a/src/controllers/dashboard/notifications/notifications/index.js +++ b/src/controllers/dashboard/notifications/notifications/index.js @@ -1,5 +1,4 @@ import loading from 'loading'; -import libraryMenu from 'libraryMenu'; import globalize from 'globalize'; import 'listViewStyle'; import 'emby-button'; diff --git a/src/controllers/livetv/livetvrecordings.js b/src/controllers/livetv/livetvrecordings.js index cb3bfeb7a6..ec2f57e14f 100644 --- a/src/controllers/livetv/livetvrecordings.js +++ b/src/controllers/livetv/livetvrecordings.js @@ -1,7 +1,5 @@ -import layoutManager from 'layoutManager'; import loading from 'loading'; import cardBuilder from 'cardBuilder'; -import appHost from 'apphost'; import imageLoader from 'imageLoader'; import 'scripts/livetvcomponents'; import 'listViewStyle'; From 8c58472dcf1b2586f71eb3e2d247d1955b3a721b Mon Sep 17 00:00:00 2001 From: matjaz321 Date: Tue, 4 Aug 2020 19:15:15 +0200 Subject: [PATCH 32/56] Migrated castSenderApi.js to es6 module --- package.json | 1 + src/components/castSenderApi.js | 50 ++++++++++++-------------- src/plugins/chromecastPlayer/plugin.js | 2 +- 3 files changed, 24 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index 1d7cf770d3..bf4d9ccf0a 100644 --- a/package.json +++ b/package.json @@ -169,6 +169,7 @@ "src/components/toast/toast.js", "src/components/upnextdialog/upnextdialog.js", "src/components/viewContainer.js", + "src/components/castSenderApi.js", "src/controllers/session/addServer/index.js", "src/controllers/session/forgotPassword/index.js", "src/controllers/session/redeemPassword/index.js", diff --git a/src/components/castSenderApi.js b/src/components/castSenderApi.js index b541c1f87a..c7fd5df217 100644 --- a/src/components/castSenderApi.js +++ b/src/components/castSenderApi.js @@ -1,34 +1,28 @@ -define([], function() { - 'use strict'; - - if (window.appMode === 'cordova' || window.appMode === 'android') { - return { - load: function () { - window.chrome = window.chrome || {}; +class CastSenderApi { + load() { + if (window.appMode === 'cordova' || window.appMode === 'android') { + window.chrome = window.chrome || {}; + return Promise.resolve(); + } else { + let ccLoaded = false; + if (ccLoaded) { return Promise.resolve(); } - }; - } else { - var ccLoaded = false; - return { - load: function () { - if (ccLoaded) { - return Promise.resolve(); - } - return new Promise(function (resolve, reject) { - var fileref = document.createElement('script'); - fileref.setAttribute('type', 'text/javascript'); + return new Promise(function (resolve) { + const fileref = document.createElement('script'); + fileref.setAttribute('type', 'text/javascript'); - fileref.onload = function () { - ccLoaded = true; - resolve(); - }; + fileref.onload = function () { + ccLoaded = true; + resolve(); + }; - fileref.setAttribute('src', 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js'); - document.querySelector('head').appendChild(fileref); - }); - } - }; + fileref.setAttribute('src', 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js'); + document.querySelector('head').appendChild(fileref); + }); + } } -}); +} + +export default CastSenderApi; diff --git a/src/plugins/chromecastPlayer/plugin.js b/src/plugins/chromecastPlayer/plugin.js index 2741a6f0e3..3d49f6fff6 100644 --- a/src/plugins/chromecastPlayer/plugin.js +++ b/src/plugins/chromecastPlayer/plugin.js @@ -577,7 +577,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', ' this.isLocalPlayer = false; this.lastPlayerData = {}; - castSenderApiLoader.load().then(initializeChromecast.bind(this)); + new castSenderApiLoader().load().then(initializeChromecast.bind(this)); } ChromecastPlayer.prototype.tryPair = function (target) { From 0963fb37486372f48aaf16fbba08218d25d2c40a Mon Sep 17 00:00:00 2001 From: millallo Date: Tue, 4 Aug 2020 21:02:48 +0000 Subject: [PATCH 33/56] Translated using Weblate (Italian) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/it/ --- src/strings/it.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strings/it.json b/src/strings/it.json index 9035251c12..15e32d84bf 100644 --- a/src/strings/it.json +++ b/src/strings/it.json @@ -157,8 +157,8 @@ "DetectingDevices": "Rilevamento dispositivi", "DeviceAccessHelp": "Si applica solo ai dispositivi che possono essere identificati univocamente e non impedirà l'accesso dal browser. Filtrare l'accesso ai dispositivi dell'utente impedirà di usare nuovi dispositivi fino a quando non saranno stati approvati qui.", "DirectPlaying": "Riproduzione Diretta", - "DirectStreamHelp1": "Il file multimediale è compatibile con il dispositivo per quanto riguarda la risoluzione e il tipo di supporto (H. 264, AC3, ecc), ma è in un contenitore file incompatibile (mkv, avi, wmv, ecc). Il video sarà ri-confezionato al volo prima di streammarlo sul dispositivo.", - "DirectStreamHelp2": "Lo Streaming in Diretta di un file utilizza poco il processore senza alcuna perdita di qualità video.", + "DirectStreamHelp1": "Il file multimediale è compatibile con il dispositivo per quanto riguarda la risoluzione e il tipo di supporto (H. 264, AC3, ecc), ma è in un contenitore file incompatibile (mkv, avi, wmv, ecc). Il video sarà quindi reimpacchettato al volo prima dell'invio al dispositivo.", + "DirectStreamHelp2": "Lo streaming in diretta utilizza poco processore e con poca perdita di qualità video.", "DirectStreaming": "Streaming Diretto", "Director": "Regista", "Directors": "Registi", @@ -265,7 +265,7 @@ "HeaderAllowMediaDeletionFrom": "Abilita Eliminazione Media Da", "HeaderApiKey": "Chiave API", "HeaderApiKeys": "Chiavi API", - "HeaderApiKeysHelp": "Le Applicazioni esterne devono avere una chiave API per comunicare con il Server Jellyfin. Le chiavi sono emesse accedendo con un account Jellyfin, o fornendo manualmente una chiave all'applicazione.", + "HeaderApiKeysHelp": "Le Applicazioni esterne devono avere una chiave API per comunicare con il server. Le chiavi sono emesse accedendo con un qualsiasi account, o fornendo manualmente una chiave all'applicazione.", "HeaderAudioBooks": "Audiolibri", "HeaderAudioSettings": "Impostazioni audio", "HeaderBlockItemsWithNoRating": "Blocca elementi sconosciuti o senza informazioni:", @@ -1281,7 +1281,7 @@ "HeaderCastCrew": "Cast", "HeaderMedia": "Media", "HeaderPassword": "Password", - "AuthProviderHelp": "Selezionare un Provider di Autenticazione da utilizzare per autenticare la password dell'utente.", + "AuthProviderHelp": "Selezionare un provider di autenticazione da utilizzare per autenticare la password dell'utente.", "HeaderFavoriteMovies": "Film Preferiti", "HeaderFavoriteShows": "Serie TV Preferite", "HeaderFavoriteEpisodes": "Episodi Preferiti", From 0e388d4d6deab055926ee7093ec051694e985e9c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2020 02:51:36 +0000 Subject: [PATCH 34/56] Bump @babel/core from 7.11.0 to 7.11.1 Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.11.0 to 7.11.1. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.11.1/packages/babel-core) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 7365d4f0e4..a014dc1b76 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "repository": "https://github.com/jellyfin/jellyfin-web", "license": "GPL-2.0-or-later", "devDependencies": { - "@babel/core": "^7.11.0", + "@babel/core": "^7.11.1", "@babel/eslint-parser": "^7.11.0", "@babel/eslint-plugin": "^7.11.0", "@babel/plugin-proposal-class-properties": "^7.10.1", diff --git a/yarn.lock b/yarn.lock index 400a7c2bee..5c8a7f7e14 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18,16 +18,16 @@ invariant "^2.2.4" semver "^5.5.0" -"@babel/core@>=7.2.2", "@babel/core@>=7.9.0", "@babel/core@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.0.tgz#73b9c33f1658506887f767c26dae07798b30df76" - integrity sha512-mkLq8nwaXmDtFmRkQ8ED/eA2CnVw4zr7dCztKalZXBvdK5EeNUAesrrwUqjQEzFgomJssayzB0aqlOsP1vGLqg== +"@babel/core@>=7.2.2", "@babel/core@>=7.9.0", "@babel/core@^7.11.1": + version "7.11.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.1.tgz#2c55b604e73a40dc21b0e52650b11c65cf276643" + integrity sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ== dependencies: "@babel/code-frame" "^7.10.4" "@babel/generator" "^7.11.0" "@babel/helper-module-transforms" "^7.11.0" "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.11.0" + "@babel/parser" "^7.11.1" "@babel/template" "^7.10.4" "@babel/traverse" "^7.11.0" "@babel/types" "^7.11.0" @@ -281,10 +281,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.10.4", "@babel/parser@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.0.tgz#a9d7e11aead25d3b422d17b2c6502c8dddef6a5d" - integrity sha512-qvRvi4oI8xii8NllyEc4MDJjuZiNaRzyb7Y7lup1NqJV8TZHF4O27CcP+72WPn/k1zkgJ6WJfnIbk4jTsVAZHw== +"@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.11.1": + version "7.11.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.1.tgz#d91a387990b21e5d20047b336bb19b0553f02ff5" + integrity sha512-u9QMIRdKVF7hfEkb3nu2LgZDIzCQPv+yHD9Eg6ruoJLjkrQ9fFz4IBSlF/9XwoNri9+2F1IY+dYuOfZrXq8t3w== "@babel/plugin-proposal-async-generator-functions@^7.10.4": version "7.10.4" From 88bbada5064c4caa5576e33c180827fd725da44d Mon Sep 17 00:00:00 2001 From: Daisuke Inoue Date: Wed, 5 Aug 2020 05:59:37 +0000 Subject: [PATCH 35/56] Translated using Weblate (Japanese) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/ja/ --- src/strings/ja.json | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/strings/ja.json b/src/strings/ja.json index 4e0a0a4fed..a6738d9517 100644 --- a/src/strings/ja.json +++ b/src/strings/ja.json @@ -169,7 +169,7 @@ "DetectingDevices": "検出デバイス", "DeviceAccessHelp": "これは、識別できるデバイスにのみ適用され、ブラウザへのアクセスを妨げることはありません。 ユーザーのデバイスアクセスをフィルタリングすると、ここで承認されるまで新しいデバイスを使用できなくなります。", "DirectPlaying": "ダイレクト再生", - "DirectStreamHelp1": "メディアの種類 (H.264, AC3, etc.)がお使いのデバイスに対応している場合Jellyfinサーバーからメディアファイルの直接再生が可能です。互換性のないファイルコンテナ(.mkv, .avi, .wmv, etc.)はリパックを行い再生されます。", + "DirectStreamHelp1": "メディアは、解像度と種類 (H.264, AC3など)がお使いのデバイスに対応していますが、ファイルコンテナ(.mkv, .avi, .wmvなど)が対応していません。ビデオはデバイスに送信される前に、再パッケージされます。", "DirectStreamHelp2": "ファイルのダイレクトストリーミングは、ビデオ品質を損なうことなく、Jellyfin Serverにもほとんど負荷がありません。", "DirectStreaming": "ダイレクトストリーミング", "Director": "ディレクター", @@ -291,7 +291,7 @@ "HeaderAllowMediaDeletionFrom": "メディアの削除を許可", "HeaderApiKey": "API キー", "HeaderApiKeys": "API キー", - "HeaderApiKeysHelp": "Jellyfin サーバーと通信するには、外部アプリケーション用ににAPIキーが必要です。 キーはJellyfinアカウントでログインするか、手動でアプリケーションにキーを付与することによって発行されます。", + "HeaderApiKeysHelp": "外部アプリケーションが Jellyfin サーバーと通信するには、API キーが必要です。キーは 通常のユーザーアカウントでログインするか、手動でアプリケーションにキーを付与することで発行します。", "HeaderApp": "アプリ", "HeaderAppearsOn": "表示", "HeaderAudioBooks": "オーディオブック", @@ -534,7 +534,7 @@ "LabelEncoderPreset": "H264エンコーディングプリセット:", "LabelHardwareAccelerationType": "ハードウェアアクセラレーション:", "LabelH264Crf": "H264エンコーディングCRF:", - "LabelHttpsPortHelp": "JellyfinのHTTPSサーバーがバインドするTCPポート番号。", + "LabelHttpsPortHelp": "HTTPS サーバーのTCPポート番号。", "LabelKodiMetadataDateFormat": "リリース日時フォーマット:", "LabelLogs": "ログ:", "LabelMessageText": "メッセージテキスト:", @@ -1136,7 +1136,7 @@ "LabelCustomCertificatePathHelp": "カスタムドメインでTLSサポートを有効にするための証明書と秘密鍵を含むPKCS #12ファイルのパス。", "LabelCachePathHelp": "画像などのサーバーキャッシュファイルの場所を指定します。空欄にしておくと、サーバーのデフォルトを使います。", "LabelBlastMessageIntervalHelp": "ブラスト アライブ メッセージ間の時間を秒単位で指定します。", - "LabelBindToLocalNetworkAddressHelp": "追加の設定。http サーバをバインドするローカル IP アドレスを上書きします。空のままにしておくと、サーバは利用可能なすべてのアドレスにバインドします。この値を変更するには、Jellyfin Server を再起動する必要があります。", + "LabelBindToLocalNetworkAddressHelp": "HTTP サーバー用のローカル IP アドレスを上書きします。空のままにしておくと、サーバーは利用可能なすべてのアドレスにバインドします。この値の変更を反映するには、Jellyfin サーバーの再起動が必要です。", "LabelAlbumArtMaxWidthHelp": "upnp:albumArtURI で公開するアルバムアートの最大解像度。", "LabelAlbumArtMaxHeightHelp": "upnp:albumArtURI で公開するアルバムアートの最大解像度。", "LabelAlbumArtHelp": "upnp:albumArtURI の dlna:profileID 属性で、アルバムアートに使われるPN。デバイスによっては、画像のサイズと無関係に特定の値を要求するものもあります。", @@ -1161,14 +1161,14 @@ "LabelEnableDlnaPlayTo": "DLNA 再生を有効にする", "LabelEnableDlnaDebugLoggingHelp": "巨大なログファイルを作成します。トラブルシューティングでの必要な際にだけ使用してください。", "LabelEnableDlnaClientDiscoveryIntervalHelp": "Jellyfin が実行する SSDP 検索の間隔を決めます(秒単位)。", - "LabelGroupMoviesIntoCollectionsHelp": "ムービーリストを表示する際、コレクションに属するムービーを1つのグループとして表示します。", - "LabelServerNameHelp": "この名前はサーバーを識別するために使用します。デフォルトではサーバーのコンピュータ名です。", + "LabelGroupMoviesIntoCollectionsHelp": "ムービー リストを表示する際、コレクションに属するムービーは1つのグループとして表示します。", + "LabelServerNameHelp": "この名前はサーバーを識別するために使用します。デフォルトではサーバーのホスト名です。", "LabelExtractChaptersDuringLibraryScanHelp": "ライブラリー スキャン中に動画を取り込んだときに、チャプター画像を生成します。もしくは、スケジュールタスクの中でチャプター画像を抽出することで、通常のライブラリー スキャンをより速く完了させることができます。", "LabelExtractChaptersDuringLibraryScan": "ライブラリーをスキャンしながら、チャプター画像を生成する", - "LabelBaseUrlHelp": "サーバーの URL にカスタム サブディレクトリを加えます。例 : http://example.com/<baseurl>", + "LabelBaseUrlHelp": "サーバーの URL に、カスタム サブディレクトリを加えます。例 : http://example.com/<baseurl>", "LabelEnableSingleImageInDidlLimitHelp": "Didl 内に複数の画像が埋め込まれている場合、一部のデバイスでは正しくレンダリングされません。", - "LabelEnableRealtimeMonitorHelp": "ファイルへの変更は、サポートされているファイルシステム上ですぐに処理されます。", - "LabelEnableHttpsHelp": "構成された HTTPS ポートからサーバーがリッスンするのを有効にします。この機能を有効にするには、適切な証明書を設定する必要があります。", + "LabelEnableRealtimeMonitorHelp": "サポートしているファイルシステムでは、ファイルの変更をすぐに処理します。", + "LabelEnableHttpsHelp": "設定した HTTPS ポートをリッスンします。この機能を有効にするには、適切な証明書の設定が必要です。", "LabelImageFetchersHelp": "画像検索サイトの優先度を設定します。", "LabelPostProcessorArgumentsHelp": "{path}を録画ファイルのパスとして使用します。", "LabelPostProcessorArguments": "後処理のコマンドライン引数:", @@ -1214,5 +1214,7 @@ "LabelKodiMetadataDateFormatHelp": "NFOファイル内の全データが,このフォーマットによって解析されます。", "LabelKeepUpTo": "最新:", "LabelInNetworkSignInWithEasyPasswordHelp": "ローカルネットワーク内では簡単なPINコードを利用してサインインするようにします。ローカル以外からのアクセスのときのみ通常のパスワードが必要になります。PINコードを空欄にした場合,ローカルネットワーク内からのアクセスではパスワードが不要になります。", - "LabelInNetworkSignInWithEasyPassword": "簡単なPINコードを利用してネットワーク内からサインインする機能の有効化" + "LabelInNetworkSignInWithEasyPassword": "簡単なPINコードを利用してネットワーク内からサインインする機能の有効化", + "LabelIconMaxWidthHelp": "upnp:icon として表示されるアイコンの最大解像度(幅)。", + "LabelIconMaxHeightHelp": "upnp:icon として表示されるアイコンの最大解像度(高さ)。" } From 91f6532e35f347e134b534f93e89d0c68e7866fa Mon Sep 17 00:00:00 2001 From: Matjaz Zavski Date: Wed, 5 Aug 2020 09:17:17 +0200 Subject: [PATCH 36/56] Update src/controllers/livetv/livetvchannels.js Co-authored-by: Julien Machiels --- src/controllers/livetv/livetvchannels.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/livetv/livetvchannels.js b/src/controllers/livetv/livetvchannels.js index d34fe58132..278200c634 100644 --- a/src/controllers/livetv/livetvchannels.js +++ b/src/controllers/livetv/livetvchannels.js @@ -91,8 +91,8 @@ export default function (view, params, tabContent) { } function showFilterMenu(context) { - import(['components/filterdialog/filterdialog']).then(({default: filterDialogFactory}) => { - const filterDialog = new filterDialogFactory({ + import(['components/filterdialog/filterdialog']).then(({default: FilterDialog}) => { + const filterDialog = new FilterDialog({ query: getQuery(), mode: 'livetvchannels', serverId: ApiClient.serverId() From 5bb37263fc8a76e9d7382bd4e8782a42fb04872f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2020 08:48:21 +0000 Subject: [PATCH 37/56] Bump gulp-terser from 1.3.0 to 1.3.2 Bumps [gulp-terser](https://github.com/duan602728596/gulp-terser) from 1.3.0 to 1.3.2. - [Release notes](https://github.com/duan602728596/gulp-terser/releases) - [Commits](https://github.com/duan602728596/gulp-terser/compare/v1.3.0...v1.3.2) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a014dc1b76..504f4038d9 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "gulp-postcss": "^8.0.0", "gulp-sass": "^4.0.2", "gulp-sourcemaps": "^2.6.5", - "gulp-terser": "^1.3.0", + "gulp-terser": "^1.3.2", "html-webpack-plugin": "^4.3.0", "lazypipe": "^1.0.2", "node-sass": "^4.13.1", diff --git a/yarn.lock b/yarn.lock index 5c8a7f7e14..3ec7f21487 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5262,11 +5262,12 @@ gulp-sourcemaps@^2.6.5: strip-bom-string "1.X" through2 "2.X" -gulp-terser@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/gulp-terser/-/gulp-terser-1.3.0.tgz#6423fdb7dd15cc376e28063b5271271a928084bd" - integrity sha512-EvizE1LJLfOh3/EmpJoq9iqYziObOkTzFgN4KvxfB0ICp3+W5H+MOO9B7Xq5Iuu9N+RKByNJLmqR+Ph13U1vtQ== +gulp-terser@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/gulp-terser/-/gulp-terser-1.3.2.tgz#c91a71c31de0c40a94330bfd43b20c2a40df9a6b" + integrity sha512-hLx9Ww9PX304R3E7pMyL+jFftH47QXQCgKE6IZajbz7OoqAPMdr+sTxBpaujgIVkdbnJwJ7AFhfrcyy/cjBgZQ== dependencies: + is-promise "^4.0.0" plugin-error "^1.0.1" terser ">=4" through2 "^4.0.2" @@ -6166,6 +6167,11 @@ is-promise@^2.1: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== +is-promise@^4.0.0: + version "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" From 2a822704d674bc32574505784819306ec36cd883 Mon Sep 17 00:00:00 2001 From: Xantios Krugor Date: Wed, 5 Aug 2020 12:19:51 +0200 Subject: [PATCH 38/56] Use focusManager.default in non ES6 modules --- src/components/filtermenu/filtermenu.js | 3 +++ src/components/guide/guide.js | 1 + src/components/slideshow/slideshow.js | 1 + src/components/sortmenu/sortmenu.js | 2 ++ src/components/subtitleeditor/subtitleeditor.js | 1 + src/components/tunerPicker.js | 1 + src/components/viewManager/viewManager.js | 2 ++ src/controllers/hometab.js | 1 + src/controllers/list.js | 1 + src/libraries/scroller.js | 3 ++- src/scripts/scrollHelper.js | 2 ++ src/scripts/serverNotifications.js | 1 + 12 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/components/filtermenu/filtermenu.js b/src/components/filtermenu/filtermenu.js index 20399fb52d..bd9bcb3c56 100644 --- a/src/components/filtermenu/filtermenu.js +++ b/src/components/filtermenu/filtermenu.js @@ -1,4 +1,7 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', 'inputManager', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'userSettings', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (require, dom, focusManager, dialogHelper, loading, appHost, inputManager, layoutManager, connectionManager, appRouter, globalize, userSettings) { + + focusManager = focusManager.default || focusManager; + 'use strict'; function onSubmit(e) { diff --git a/src/components/guide/guide.js b/src/components/guide/guide.js index 61caa9188f..71d63f82c0 100644 --- a/src/components/guide/guide.js +++ b/src/components/guide/guide.js @@ -4,6 +4,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', playbackManager = playbackManager.default || playbackManager; browser = browser.default || browser; loading = loading.default || loading; + focusManager = focusManager.default || focusManager; function showViewSettings(instance) { require(['guide-settings-dialog'], function (guideSettingsDialog) { diff --git a/src/components/slideshow/slideshow.js b/src/components/slideshow/slideshow.js index 60c458e234..38728ec6c6 100644 --- a/src/components/slideshow/slideshow.js +++ b/src/components/slideshow/slideshow.js @@ -6,6 +6,7 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f 'use strict'; browser = browser.default || browser; + focusManager = focusManager.default || focusManager; /** * Name of transition event. diff --git a/src/components/sortmenu/sortmenu.js b/src/components/sortmenu/sortmenu.js index f62e5bb3a4..52a7b95c40 100644 --- a/src/components/sortmenu/sortmenu.js +++ b/src/components/sortmenu/sortmenu.js @@ -1,6 +1,8 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'layoutManager', 'connectionManager', 'globalize', 'userSettings', 'emby-select', 'paper-icon-button-light', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (require, dom, focusManager, dialogHelper, loading, layoutManager, connectionManager, globalize, userSettings) { 'use strict'; + focusManager = focusManager.default || focusManager; + function onSubmit(e) { e.preventDefault(); return false; diff --git a/src/components/subtitleeditor/subtitleeditor.js b/src/components/subtitleeditor/subtitleeditor.js index 7df24b5da8..c42658b2d5 100644 --- a/src/components/subtitleeditor/subtitleeditor.js +++ b/src/components/subtitleeditor/subtitleeditor.js @@ -2,6 +2,7 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', 'use strict'; loading = loading.default || loading; + focusManager = focusManager.default || focusManager; var currentItem; var hasChanges; diff --git a/src/components/tunerPicker.js b/src/components/tunerPicker.js index 5bc9386053..4e78030a2a 100644 --- a/src/components/tunerPicker.js +++ b/src/components/tunerPicker.js @@ -3,6 +3,7 @@ define(['dialogHelper', 'dom', 'layoutManager', 'connectionManager', 'globalize' browser = browser.default || browser; loading = loading.default || loading; + focusManager = focusManager.default || focusManager; var enableFocusTransform = !browser.slow && !browser.edge; diff --git a/src/components/viewManager/viewManager.js b/src/components/viewManager/viewManager.js index 058ba4ebb2..55425994d2 100644 --- a/src/components/viewManager/viewManager.js +++ b/src/components/viewManager/viewManager.js @@ -1,6 +1,8 @@ define(['viewContainer', 'focusManager', 'queryString', 'layoutManager'], function (viewContainer, focusManager, queryString, layoutManager) { 'use strict'; + focusManager = focusManager.default || focusManager; + var currentView; var dispatchPageEvents; diff --git a/src/controllers/hometab.js b/src/controllers/hometab.js index 97034d4505..9610efbd39 100644 --- a/src/controllers/hometab.js +++ b/src/controllers/hometab.js @@ -2,6 +2,7 @@ define(['userSettings', 'loading', 'connectionManager', 'apphost', 'layoutManage 'use strict'; loading = loading.default || loading; + focusManager = focusManager.default || focusManager; function HomeTab(view, params) { this.view = view; diff --git a/src/controllers/list.js b/src/controllers/list.js index a35b7a0cf9..77830badaf 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -3,6 +3,7 @@ define(['globalize', 'listView', 'layoutManager', 'userSettings', 'focusManager' playbackManager = playbackManager.default || playbackManager; loading = loading.default || loading; + focusManager = focusManager.default || focusManager; function getInitialLiveTvQuery(instance, params) { var query = { diff --git a/src/libraries/scroller.js b/src/libraries/scroller.js index d869d8c8be..cc75dcdeef 100644 --- a/src/libraries/scroller.js +++ b/src/libraries/scroller.js @@ -2,6 +2,7 @@ define(['browser', 'layoutManager', 'dom', 'focusManager', 'ResizeObserver', 'sc 'use strict'; browser = browser.default || browser; + focusManager = focusManager.default || focusManager; /** * Return type of the value. @@ -697,7 +698,7 @@ define(['browser', 'layoutManager', 'dom', 'focusManager', 'ResizeObserver', 'sc function onFrameClick(e) { if (e.which === 1) { - var focusableParent = focusManager.default.focusableParent(e.target); + var focusableParent = focusManager.focusableParent(e.target); if (focusableParent && focusableParent !== document.activeElement) { focusableParent.focus(); } diff --git a/src/scripts/scrollHelper.js b/src/scripts/scrollHelper.js index 82413fe9cf..8b596571b4 100644 --- a/src/scripts/scrollHelper.js +++ b/src/scripts/scrollHelper.js @@ -1,6 +1,8 @@ define(['focusManager', 'dom', 'scrollStyles'], function (focusManager, dom) { 'use strict'; + focusManager = focusManager.default || focusManager; + function getBoundingClientRect(elem) { // Support: BlackBerry 5, iOS 3 (original iPhone) // If we don't have gBCR, just use 0,0 rather than error diff --git a/src/scripts/serverNotifications.js b/src/scripts/serverNotifications.js index e5fb0bcd61..87db52402d 100644 --- a/src/scripts/serverNotifications.js +++ b/src/scripts/serverNotifications.js @@ -2,6 +2,7 @@ define(['connectionManager', 'playbackManager', 'syncPlayManager', 'events', 'in 'use strict'; playbackManager = playbackManager.default || playbackManager; + focusManager = focusManager.default || focusManager; var serverNotifications = {}; From 8a16793b971e960e9e0208450c7e00ff43f8e71c Mon Sep 17 00:00:00 2001 From: Xantios Krugor Date: Wed, 5 Aug 2020 12:24:26 +0200 Subject: [PATCH 39/56] Note to self: lint first, commit later --- src/components/filtermenu/filtermenu.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/filtermenu/filtermenu.js b/src/components/filtermenu/filtermenu.js index bd9bcb3c56..b02b5fb9f8 100644 --- a/src/components/filtermenu/filtermenu.js +++ b/src/components/filtermenu/filtermenu.js @@ -1,8 +1,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', 'inputManager', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'userSettings', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (require, dom, focusManager, dialogHelper, loading, appHost, inputManager, layoutManager, connectionManager, appRouter, globalize, userSettings) { - - focusManager = focusManager.default || focusManager; - 'use strict'; + focusManager = focusManager.default || focusManager; function onSubmit(e) { e.preventDefault(); From 53d654261344b9a614e29fac700cfb76795c3d62 Mon Sep 17 00:00:00 2001 From: Cameron Date: Wed, 5 Aug 2020 11:48:31 +0100 Subject: [PATCH 40/56] Migration of recordinghelper and seriesrecordingeditor to ES6 modules --- package.json | 2 + .../recordingcreator/recordingbutton.js | 2 + .../recordingcreator/recordingeditor.js | 2 + .../recordingcreator/recordingfields.js | 1 + .../recordingcreator/recordinghelper.js | 337 +++++++------- .../recordingcreator/seriesrecordingeditor.js | 414 +++++++++--------- 6 files changed, 390 insertions(+), 368 deletions(-) diff --git a/package.json b/package.json index 8408217bf3..5277ea3a9e 100644 --- a/package.json +++ b/package.json @@ -152,6 +152,8 @@ "src/components/playlisteditor/playlisteditor.js", "src/components/playmenu.js", "src/components/prompt/prompt.js", + "src/components/recordingcreator/seriesrecordingeditor.js", + "src/components/recordingcreator/recordinghelper.js", "src/components/refreshdialog/refreshdialog.js", "src/components/sanatizefilename.js", "src/components/scrollManager.js", diff --git a/src/components/recordingcreator/recordingbutton.js b/src/components/recordingcreator/recordingbutton.js index 3ad4ffa594..1207208e90 100644 --- a/src/components/recordingcreator/recordingbutton.js +++ b/src/components/recordingcreator/recordingbutton.js @@ -1,6 +1,8 @@ define(['globalize', 'connectionManager', 'require', 'loading', 'apphost', 'dom', 'recordingHelper', 'events', 'paper-icon-button-light', 'emby-button', 'css!./recordingfields'], function (globalize, connectionManager, require, loading, appHost, dom, recordingHelper, events) { 'use strict'; + recordingHelper = recordingHelper.default || recordingHelper; + function onRecordingButtonClick(e) { var item = this.item; diff --git a/src/components/recordingcreator/recordingeditor.js b/src/components/recordingcreator/recordingeditor.js index 2086129a9e..2e54b3601c 100644 --- a/src/components/recordingcreator/recordingeditor.js +++ b/src/components/recordingcreator/recordingeditor.js @@ -12,6 +12,8 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c function deleteTimer(apiClient, timerId) { return new Promise(function (resolve, reject) { require(['recordingHelper'], function (recordingHelper) { + recordingHelper = recordingHelper.default || recordingHelper; + recordingHelper.cancelTimerWithConfirmation(timerId, apiClient.serverId()).then(resolve, reject); }); }); diff --git a/src/components/recordingcreator/recordingfields.js b/src/components/recordingcreator/recordingfields.js index e3739f1cfe..741570581e 100644 --- a/src/components/recordingcreator/recordingfields.js +++ b/src/components/recordingcreator/recordingfields.js @@ -1,6 +1,7 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loading', 'apphost', 'dom', 'recordingHelper', 'events', 'paper-icon-button-light', 'emby-button', 'css!./recordingfields', 'flexStyles'], function (globalize, connectionManager, serverNotifications, require, loading, appHost, dom, recordingHelper, events) { 'use strict'; + recordingHelper = recordingHelper.default || recordingHelper; loading = loading.default || loading; function loadData(parent, program, apiClient) { diff --git a/src/components/recordingcreator/recordinghelper.js b/src/components/recordingcreator/recordinghelper.js index 5d72394282..13359de2bc 100644 --- a/src/components/recordingcreator/recordinghelper.js +++ b/src/components/recordingcreator/recordinghelper.js @@ -1,194 +1,195 @@ -define(['globalize', 'loading', 'connectionManager'], function (globalize, loading, connectionManager) { - 'use strict'; +import globalize from 'globalize'; +import loading from 'loading'; +import connectionManager from 'connectionManager'; - loading = loading.default || loading; +/*eslint prefer-const: "error"*/ - function changeRecordingToSeries(apiClient, timerId, programId, confirmTimerCancellation) { - loading.show(); +function changeRecordingToSeries(apiClient, timerId, programId, confirmTimerCancellation) { + loading.show(); - return apiClient.getItem(apiClient.getCurrentUserId(), programId).then(function (item) { - if (item.IsSeries) { - // create series - return apiClient.getNewLiveTvTimerDefaults({ programId: programId }).then(function (timerDefaults) { - return apiClient.createLiveTvSeriesTimer(timerDefaults).then(function () { - loading.hide(); - sendToast(globalize.translate('SeriesRecordingScheduled')); + return apiClient.getItem(apiClient.getCurrentUserId(), programId).then(function (item) { + if (item.IsSeries) { + // create series + return apiClient.getNewLiveTvTimerDefaults({ programId: programId }).then(function (timerDefaults) { + return apiClient.createLiveTvSeriesTimer(timerDefaults).then(function () { + loading.hide(); + sendToast(globalize.translate('SeriesRecordingScheduled')); + }); + }); + } else { + // cancel + if (confirmTimerCancellation) { + return cancelTimerWithConfirmation(timerId, apiClient.serverId()); + } + + return cancelTimer(apiClient.serverId(), timerId, true); + } + }); +} + +function cancelTimerWithConfirmation(timerId, serverId) { + return new Promise(function (resolve, reject) { + import('confirm').then(({ default: confirm }) => { + confirm.default({ + + text: globalize.translate('MessageConfirmRecordingCancellation'), + primary: 'delete', + confirmText: globalize.translate('HeaderCancelRecording'), + cancelText: globalize.translate('HeaderKeepRecording') + + }).then(function () { + loading.show(); + + const apiClient = connectionManager.getApiClient(serverId); + cancelTimer(apiClient, timerId, true).then(resolve, reject); + }, reject); + }); + }); +} + +function cancelSeriesTimerWithConfirmation(timerId, serverId) { + return new Promise(function (resolve, reject) { + import('confirm').then(({ default: confirm }) => { + confirm.default({ + + text: globalize.translate('MessageConfirmRecordingCancellation'), + primary: 'delete', + confirmText: globalize.translate('HeaderCancelSeries'), + cancelText: globalize.translate('HeaderKeepSeries') + + }).then(function () { + loading.show(); + + const apiClient = connectionManager.getApiClient(serverId); + apiClient.cancelLiveTvSeriesTimer(timerId).then(function () { + import('toast').then(({default: toast}) => { + toast(globalize.translate('SeriesCancelled')); }); + + loading.hide(); + resolve(); + }, reject); + }, reject); + }); + }); +} + +function cancelTimer(apiClient, timerId, hideLoading) { + loading.show(); + return apiClient.cancelLiveTvTimer(timerId).then(function () { + if (hideLoading !== false) { + loading.hide(); + sendToast(globalize.translate('RecordingCancelled')); + } + }); +} + +function createRecording(apiClient, programId, isSeries) { + loading.show(); + return apiClient.getNewLiveTvTimerDefaults({ programId: programId }).then(function (item) { + const promise = isSeries ? + apiClient.createLiveTvSeriesTimer(item) : + apiClient.createLiveTvTimer(item); + + return promise.then(function () { + loading.hide(); + sendToast(globalize.translate('RecordingScheduled')); + }); + }); +} + +function sendToast(msg) { + import('toast').then(({ default: toast }) => { + toast(msg); + }); +} + +function showMultiCancellationPrompt(serverId, programId, timerId, timerStatus, seriesTimerId) { + return new Promise(function (resolve, reject) { + import('dialog').then(({ default: dialog }) => { + const items = []; + + items.push({ + name: globalize.translate('HeaderKeepRecording'), + id: 'cancel', + type: 'submit' + }); + + if (timerStatus === 'InProgress') { + items.push({ + name: globalize.translate('HeaderStopRecording'), + id: 'canceltimer', + type: 'cancel' }); } else { - // cancel - if (confirmTimerCancellation) { - return cancelTimerWithConfirmation(timerId, apiClient.serverId()); - } - - return cancelTimer(apiClient.serverId(), timerId, true); + items.push({ + name: globalize.translate('HeaderCancelRecording'), + id: 'canceltimer', + type: 'cancel' + }); } - }); - } - function cancelTimerWithConfirmation(timerId, serverId) { - return new Promise(function (resolve, reject) { - require(['confirm'], function (confirm) { - confirm.default({ - - text: globalize.translate('MessageConfirmRecordingCancellation'), - primary: 'delete', - confirmText: globalize.translate('HeaderCancelRecording'), - cancelText: globalize.translate('HeaderKeepRecording') - - }).then(function () { - loading.show(); - - var apiClient = connectionManager.getApiClient(serverId); - cancelTimer(apiClient, timerId, true).then(resolve, reject); - }, reject); + items.push({ + name: globalize.translate('HeaderCancelSeries'), + id: 'cancelseriestimer', + type: 'cancel' }); - }); - } - function cancelSeriesTimerWithConfirmation(timerId, serverId) { - return new Promise(function (resolve, reject) { - require(['confirm'], function (confirm) { - confirm.default({ + dialog({ - text: globalize.translate('MessageConfirmRecordingCancellation'), - primary: 'delete', - confirmText: globalize.translate('HeaderCancelSeries'), - cancelText: globalize.translate('HeaderKeepSeries') + text: globalize.translate('MessageConfirmRecordingCancellation'), + buttons: items - }).then(function () { + }).then(function (result) { + const apiClient = connectionManager.getApiClient(serverId); + + if (result === 'canceltimer') { loading.show(); - var apiClient = connectionManager.getApiClient(serverId); - apiClient.cancelLiveTvSeriesTimer(timerId).then(function () { - require(['toast'], function (toast) { + cancelTimer(apiClient, timerId, true).then(resolve, reject); + } else if (result === 'cancelseriestimer') { + loading.show(); + + apiClient.cancelLiveTvSeriesTimer(seriesTimerId).then(function () { + import('toast').then(({ default: toast }) => { toast(globalize.translate('SeriesCancelled')); }); loading.hide(); resolve(); }, reject); - }, reject); - }); - }); - } - - function cancelTimer(apiClient, timerId, hideLoading) { - loading.show(); - return apiClient.cancelLiveTvTimer(timerId).then(function () { - if (hideLoading !== false) { - loading.hide(); - sendToast(globalize.translate('RecordingCancelled')); - } - }); - } - - function createRecording(apiClient, programId, isSeries) { - loading.show(); - return apiClient.getNewLiveTvTimerDefaults({ programId: programId }).then(function (item) { - var promise = isSeries ? - apiClient.createLiveTvSeriesTimer(item) : - apiClient.createLiveTvTimer(item); - - return promise.then(function () { - loading.hide(); - sendToast(globalize.translate('RecordingScheduled')); - }); - }); - } - - function sendToast(msg) { - require(['toast'], function (toast) { - toast(msg); - }); - } - - function showMultiCancellationPrompt(serverId, programId, timerId, timerStatus, seriesTimerId) { - return new Promise(function (resolve, reject) { - require(['dialog'], function (dialog) { - var items = []; - - items.push({ - name: globalize.translate('HeaderKeepRecording'), - id: 'cancel', - type: 'submit' - }); - - if (timerStatus === 'InProgress') { - items.push({ - name: globalize.translate('HeaderStopRecording'), - id: 'canceltimer', - type: 'cancel' - }); } else { - items.push({ - name: globalize.translate('HeaderCancelRecording'), - id: 'canceltimer', - type: 'cancel' - }); + resolve(); } - - items.push({ - name: globalize.translate('HeaderCancelSeries'), - id: 'cancelseriestimer', - type: 'cancel' - }); - - dialog({ - - text: globalize.translate('MessageConfirmRecordingCancellation'), - buttons: items - - }).then(function (result) { - var apiClient = connectionManager.getApiClient(serverId); - - if (result === 'canceltimer') { - loading.show(); - - cancelTimer(apiClient, timerId, true).then(resolve, reject); - } else if (result === 'cancelseriestimer') { - loading.show(); - - apiClient.cancelLiveTvSeriesTimer(seriesTimerId).then(function () { - require(['toast'], function (toast) { - toast(globalize.translate('SeriesCancelled')); - }); - - loading.hide(); - resolve(); - }, reject); - } else { - resolve(); - } - }, reject); - }); + }, reject); }); - } + }); +} - function toggleRecording(serverId, programId, timerId, timerStatus, seriesTimerId) { - var apiClient = connectionManager.getApiClient(serverId); - var hasTimer = timerId && timerStatus !== 'Cancelled'; - if (seriesTimerId && hasTimer) { - // cancel - return showMultiCancellationPrompt(serverId, programId, timerId, timerStatus, seriesTimerId); - } else if (hasTimer && programId) { - // change to series recording, if possible - // otherwise cancel individual recording - return changeRecordingToSeries(apiClient, timerId, programId, true); - } else if (programId) { - // schedule recording - return createRecording(apiClient, programId); - } else { - return Promise.reject(); - } +function toggleRecording(serverId, programId, timerId, timerStatus, seriesTimerId) { + const apiClient = connectionManager.getApiClient(serverId); + const hasTimer = timerId && timerStatus !== 'Cancelled'; + if (seriesTimerId && hasTimer) { + // cancel + return showMultiCancellationPrompt(serverId, programId, timerId, timerStatus, seriesTimerId); + } else if (hasTimer && programId) { + // change to series recording, if possible + // otherwise cancel individual recording + return changeRecordingToSeries(apiClient, timerId, programId, true); + } else if (programId) { + // schedule recording + return createRecording(apiClient, programId); + } else { + return Promise.reject(); } +} + +export default { + cancelTimer: cancelTimer, + createRecording: createRecording, + changeRecordingToSeries: changeRecordingToSeries, + toggleRecording: toggleRecording, + cancelTimerWithConfirmation: cancelTimerWithConfirmation, + cancelSeriesTimerWithConfirmation: cancelSeriesTimerWithConfirmation +}; - return { - cancelTimer: cancelTimer, - createRecording: createRecording, - changeRecordingToSeries: changeRecordingToSeries, - toggleRecording: toggleRecording, - cancelTimerWithConfirmation: cancelTimerWithConfirmation, - cancelSeriesTimerWithConfirmation: cancelSeriesTimerWithConfirmation - }; -}); diff --git a/src/components/recordingcreator/seriesrecordingeditor.js b/src/components/recordingcreator/seriesrecordingeditor.js index b115e273e6..48fbbcf22c 100644 --- a/src/components/recordingcreator/seriesrecordingeditor.js +++ b/src/components/recordingcreator/seriesrecordingeditor.js @@ -1,143 +1,200 @@ -define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'connectionManager', 'require', 'loading', 'scrollHelper', 'imageLoader', 'datetime', 'scrollStyles', 'emby-button', 'emby-checkbox', 'emby-input', 'emby-select', 'paper-icon-button-light', 'css!./../formdialog', 'css!./recordingcreator', 'material-icons', 'flexStyles'], function (dialogHelper, globalize, layoutManager, mediaInfo, appHost, connectionManager, require, loading, scrollHelper, imageLoader, datetime) { - 'use strict'; +import dialogHelper from 'dialogHelper'; +import globalize from 'globalize'; +import layoutManager from 'layoutManager'; +import connectionManager from 'connectionManager'; +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'; - loading = loading.default || loading; +/*eslint prefer-const: "error"*/ - var currentDialog; - var recordingUpdated = false; - var recordingDeleted = false; - var currentItemId; - var currentServerId; +let currentDialog; +let recordingUpdated = false; +let recordingDeleted = false; +let currentItemId; +let currentServerId; - function deleteTimer(apiClient, timerId) { - return new Promise(function (resolve, reject) { - require(['recordingHelper'], function (recordingHelper) { - recordingHelper.cancelSeriesTimerWithConfirmation(timerId, apiClient.serverId()).then(resolve, reject); - }); +function deleteTimer(apiClient, timerId) { + return new Promise(function (resolve, reject) { + import('recordingHelper').then(({ default: recordingHelper }) => { + recordingHelper.cancelSeriesTimerWithConfirmation(timerId, apiClient.serverId()).then(resolve, reject); }); + }); +} + +function renderTimer(context, item) { + context.querySelector('#txtPrePaddingMinutes').value = item.PrePaddingSeconds / 60; + context.querySelector('#txtPostPaddingMinutes').value = item.PostPaddingSeconds / 60; + + context.querySelector('.selectChannels').value = item.RecordAnyChannel ? 'all' : 'one'; + context.querySelector('.selectAirTime').value = item.RecordAnyTime ? 'any' : 'original'; + + context.querySelector('.selectShowType').value = item.RecordNewOnly ? 'new' : 'all'; + context.querySelector('.chkSkipEpisodesInLibrary').checked = item.SkipEpisodesInLibrary; + context.querySelector('.selectKeepUpTo').value = item.KeepUpTo || 0; + + if (item.ChannelName || item.ChannelNumber) { + context.querySelector('.optionChannelOnly').innerHTML = globalize.translate('ChannelNameOnly', item.ChannelName || item.ChannelNumber); + } else { + context.querySelector('.optionChannelOnly').innerHTML = globalize.translate('OneChannel'); } - function renderTimer(context, item, apiClient) { - context.querySelector('#txtPrePaddingMinutes').value = item.PrePaddingSeconds / 60; - context.querySelector('#txtPostPaddingMinutes').value = item.PostPaddingSeconds / 60; + context.querySelector('.optionAroundTime').innerHTML = globalize.translate('AroundTime', datetime.getDisplayTime(datetime.parseISO8601Date(item.StartDate))); - context.querySelector('.selectChannels').value = item.RecordAnyChannel ? 'all' : 'one'; - context.querySelector('.selectAirTime').value = item.RecordAnyTime ? 'any' : 'original'; + loading.hide(); +} - context.querySelector('.selectShowType').value = item.RecordNewOnly ? 'new' : 'all'; - context.querySelector('.chkSkipEpisodesInLibrary').checked = item.SkipEpisodesInLibrary; - context.querySelector('.selectKeepUpTo').value = item.KeepUpTo || 0; +function closeDialog(isDeleted) { + recordingUpdated = true; + recordingDeleted = isDeleted; - if (item.ChannelName || item.ChannelNumber) { - context.querySelector('.optionChannelOnly').innerHTML = globalize.translate('ChannelNameOnly', item.ChannelName || item.ChannelNumber); - } else { - context.querySelector('.optionChannelOnly').innerHTML = globalize.translate('OneChannel'); - } + dialogHelper.close(currentDialog); +} - context.querySelector('.optionAroundTime').innerHTML = globalize.translate('AroundTime', datetime.getDisplayTime(datetime.parseISO8601Date(item.StartDate))); +function onSubmit(e) { + const form = this; + const apiClient = connectionManager.getApiClient(currentServerId); + + apiClient.getLiveTvSeriesTimer(currentItemId).then(function (item) { + item.PrePaddingSeconds = form.querySelector('#txtPrePaddingMinutes').value * 60; + item.PostPaddingSeconds = form.querySelector('#txtPostPaddingMinutes').value * 60; + item.RecordAnyChannel = form.querySelector('.selectChannels').value === 'all'; + item.RecordAnyTime = form.querySelector('.selectAirTime').value === 'any'; + item.RecordNewOnly = form.querySelector('.selectShowType').value === 'new'; + item.SkipEpisodesInLibrary = form.querySelector('.chkSkipEpisodesInLibrary').checked; + item.KeepUpTo = form.querySelector('.selectKeepUpTo').value; + + apiClient.updateLiveTvSeriesTimer(item); + }); + + e.preventDefault(); + + // Disable default form submission + return false; +} + +function init(context) { + fillKeepUpTo(context); + + context.querySelector('.btnCancel').addEventListener('click', function () { + closeDialog(false); + }); + + context.querySelector('.btnCancelRecording').addEventListener('click', function () { + const apiClient = connectionManager.getApiClient(currentServerId); + deleteTimer(apiClient, currentItemId).then(function () { + closeDialog(true); + }); + }); + + context.querySelector('form').addEventListener('submit', onSubmit); +} + +function reload(context, id) { + const apiClient = connectionManager.getApiClient(currentServerId); + + loading.show(); + if (typeof id === 'string') { + currentItemId = id; + + apiClient.getLiveTvSeriesTimer(id).then(function (result) { + renderTimer(context, result); + loading.hide(); + }); + } else if (id) { + currentItemId = id.Id; + + renderTimer(context, id); loading.hide(); } +} - function closeDialog(isDeleted) { - recordingUpdated = true; - recordingDeleted = isDeleted; +function fillKeepUpTo(context) { + let html = ''; - dialogHelper.close(currentDialog); - } + for (let i = 0; i <= 50; i++) { + let text; - function onSubmit(e) { - var form = this; - - var apiClient = connectionManager.getApiClient(currentServerId); - - apiClient.getLiveTvSeriesTimer(currentItemId).then(function (item) { - item.PrePaddingSeconds = form.querySelector('#txtPrePaddingMinutes').value * 60; - item.PostPaddingSeconds = form.querySelector('#txtPostPaddingMinutes').value * 60; - item.RecordAnyChannel = form.querySelector('.selectChannels').value === 'all'; - item.RecordAnyTime = form.querySelector('.selectAirTime').value === 'any'; - item.RecordNewOnly = form.querySelector('.selectShowType').value === 'new'; - item.SkipEpisodesInLibrary = form.querySelector('.chkSkipEpisodesInLibrary').checked; - item.KeepUpTo = form.querySelector('.selectKeepUpTo').value; - - apiClient.updateLiveTvSeriesTimer(item); - }); - - e.preventDefault(); - - // Disable default form submission - return false; - } - - function init(context) { - fillKeepUpTo(context); - - context.querySelector('.btnCancel').addEventListener('click', function () { - closeDialog(false); - }); - - context.querySelector('.btnCancelRecording').addEventListener('click', function () { - var apiClient = connectionManager.getApiClient(currentServerId); - deleteTimer(apiClient, currentItemId).then(function () { - closeDialog(true); - }); - }); - - context.querySelector('form').addEventListener('submit', onSubmit); - } - - function reload(context, id) { - var apiClient = connectionManager.getApiClient(currentServerId); - - loading.show(); - if (typeof id === 'string') { - currentItemId = id; - - apiClient.getLiveTvSeriesTimer(id).then(function (result) { - renderTimer(context, result, apiClient); - loading.hide(); - }); - } else if (id) { - currentItemId = id.Id; - - renderTimer(context, id, apiClient); - loading.hide(); - } - } - - function fillKeepUpTo(context) { - var html = ''; - - for (var i = 0; i <= 50; i++) { - var text; - - if (i === 0) { - text = globalize.translate('AsManyAsPossible'); - } else if (i === 1) { - text = globalize.translate('ValueOneEpisode'); - } else { - text = globalize.translate('ValueEpisodeCount', i); - } - - html += ''; + if (i === 0) { + text = globalize.translate('AsManyAsPossible'); + } else if (i === 1) { + text = globalize.translate('ValueOneEpisode'); + } else { + text = globalize.translate('ValueEpisodeCount', i); } - context.querySelector('.selectKeepUpTo').innerHTML = html; + html += ''; } - function onFieldChange(e) { - this.querySelector('.btnSubmit').click(); - } + context.querySelector('.selectKeepUpTo').innerHTML = html; +} - function embed(itemId, serverId, options) { +function onFieldChange() { + this.querySelector('.btnSubmit').click(); +} + +function embed(itemId, serverId, options) { + recordingUpdated = false; + recordingDeleted = false; + currentServerId = serverId; + loading.show(); + options = options || {}; + + import('text!./seriesrecordingeditor.template.html').then(({ default: template }) => { + const dialogOptions = { + removeOnClose: true, + scrollY: false + }; + + if (layoutManager.tv) { + dialogOptions.size = 'fullscreen'; + } else { + dialogOptions.size = 'small'; + } + + const dlg = options.context; + + dlg.classList.add('hide'); + dlg.innerHTML = globalize.translateHtml(template, 'core'); + + dlg.querySelector('.formDialogHeader').classList.add('hide'); + dlg.querySelector('.formDialogFooter').classList.add('hide'); + dlg.querySelector('.formDialogContent').className = ''; + dlg.querySelector('.dialogContentInner').className = ''; + dlg.classList.remove('hide'); + + dlg.removeEventListener('change', onFieldChange); + dlg.addEventListener('change', onFieldChange); + + currentDialog = dlg; + + init(dlg); + + reload(dlg, itemId); + }); +} + +function showEditor(itemId, serverId, options) { + return new Promise(function (resolve, reject) { recordingUpdated = false; recordingDeleted = false; currentServerId = serverId; loading.show(); options = options || {}; - require(['text!./seriesrecordingeditor.template.html'], function (template) { - var dialogOptions = { + import('text!./seriesrecordingeditor.template.html').then(({ default: template }) => { + const dialogOptions = { removeOnClose: true, scrollY: false }; @@ -148,101 +205,58 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c dialogOptions.size = 'small'; } - var dlg = options.context; + const dlg = dialogHelper.createDialog(dialogOptions); - dlg.classList.add('hide'); - dlg.innerHTML = globalize.translateHtml(template, 'core'); + dlg.classList.add('formDialog'); + dlg.classList.add('recordingDialog'); - dlg.querySelector('.formDialogHeader').classList.add('hide'); - dlg.querySelector('.formDialogFooter').classList.add('hide'); - dlg.querySelector('.formDialogContent').className = ''; - dlg.querySelector('.dialogContentInner').className = ''; - dlg.classList.remove('hide'); + if (!layoutManager.tv) { + dlg.style['min-width'] = '20%'; + } - dlg.removeEventListener('change', onFieldChange); - dlg.addEventListener('change', onFieldChange); + let html = ''; + + html += globalize.translateHtml(template, 'core'); + + dlg.innerHTML = html; + + if (options.enableCancel === false) { + dlg.querySelector('.formDialogFooter').classList.add('hide'); + } currentDialog = dlg; + dlg.addEventListener('closing', function () { + if (!recordingDeleted) { + this.querySelector('.btnSubmit').click(); + } + }); + + dlg.addEventListener('close', function () { + if (recordingUpdated) { + resolve({ + updated: true, + deleted: recordingDeleted + }); + } else { + reject(); + } + }); + + if (layoutManager.tv) { + scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false); + } + init(dlg); reload(dlg, itemId); + + dialogHelper.open(dlg); }); - } + }); +} - function showEditor(itemId, serverId, options) { - return new Promise(function (resolve, reject) { - recordingUpdated = false; - recordingDeleted = false; - currentServerId = serverId; - loading.show(); - options = options || {}; - - require(['text!./seriesrecordingeditor.template.html'], function (template) { - 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('recordingDialog'); - - if (!layoutManager.tv) { - dlg.style['min-width'] = '20%'; - } - - var html = ''; - - html += globalize.translateHtml(template, 'core'); - - dlg.innerHTML = html; - - if (options.enableCancel === false) { - dlg.querySelector('.formDialogFooter').classList.add('hide'); - } - - currentDialog = dlg; - - dlg.addEventListener('closing', function () { - if (!recordingDeleted) { - this.querySelector('.btnSubmit').click(); - } - }); - - dlg.addEventListener('close', function () { - if (recordingUpdated) { - resolve({ - updated: true, - deleted: recordingDeleted - }); - } else { - reject(); - } - }); - - if (layoutManager.tv) { - scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false); - } - - init(dlg); - - reload(dlg, itemId); - - dialogHelper.open(dlg); - }); - }); - } - - return { - show: showEditor, - embed: embed - }; -}); +export default { + show: showEditor, + embed: embed +}; From 839dcbf8618c655ee4175eecc6b1fa92e64eb486 Mon Sep 17 00:00:00 2001 From: Xantios Krugor Date: Wed, 5 Aug 2020 14:38:23 +0200 Subject: [PATCH 41/56] Update src/controllers/list.js Co-authored-by: Cameron --- src/controllers/list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/list.js b/src/controllers/list.js index 77830badaf..afa0a60fa8 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -772,7 +772,7 @@ define(['globalize', 'listView', 'layoutManager', 'userSettings', 'focusManager' loading.hide(); if (refresh) { - focusManager.default.autoFocus(self.itemsContainer); + focusManager.autoFocus(self.itemsContainer); } }); From e53eacc949dace9961d841375c28fdcbeef04d5f Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Wed, 5 Aug 2020 11:53:31 -0400 Subject: [PATCH 42/56] Add start script as alias for serve --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 504f4038d9..e6697051d2 100644 --- a/package.json +++ b/package.json @@ -318,6 +318,7 @@ "Firefox ESR" ], "scripts": { + "start": "yarn serve", "serve": "gulp serve --development", "prepare": "gulp --production", "build:development": "gulp --development", From 83300e6bf6bc45b15817e348793b0555b9fb30f5 Mon Sep 17 00:00:00 2001 From: sharkykh Date: Wed, 5 Aug 2020 18:12:31 +0000 Subject: [PATCH 43/56] Translated using Weblate (Hebrew) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/he/ --- src/strings/he.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/strings/he.json b/src/strings/he.json index 3db7c86f26..ae274c26c8 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -760,5 +760,9 @@ "ButtonSyncPlay": "SyncPlay", "ButtonPlayer": "נגן", "StopPlayback": "הפסק הפעלה", - "ClearQueue": "נקה תור" + "ClearQueue": "נקה תור", + "DashboardServerName": "שרת: {0}", + "DashboardVersionNumber": "גירסה: {0}", + "DashboardArchitecture": "ארכיטקטורה: {0}", + "DashboardOperatingSystem": "מערכת הפעלה: {0}" } From f81126844d2411f48090d06ed75a5183e13ffd27 Mon Sep 17 00:00:00 2001 From: Accendit Date: Wed, 5 Aug 2020 17:07:43 +0000 Subject: [PATCH 44/56] Translated using Weblate (Dutch) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/nl/ --- src/strings/nl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/nl.json b/src/strings/nl.json index 39b2ea1b5e..860783b083 100644 --- a/src/strings/nl.json +++ b/src/strings/nl.json @@ -1441,7 +1441,7 @@ "Season": "Seizoen", "PreferEmbeddedEpisodeInfosOverFileNames": "Verkies ingeladen afleveringsinformatie boven bestandsnaam", "PreferEmbeddedEpisodeInfosOverFileNamesHelp": "Dit gebruikt de afleveringsinformatie van de ingeladen metadata als deze aanwezig is.", - "PlaybackErrorNoCompatibleStream": "Deze machine is niet leesbaar met de media en de server verstuurd geen leesbare media formaten.", + "PlaybackErrorNoCompatibleStream": "Dit apparaat ondersteund de afgespeelde media niet en de server verstuurd geen ondersteund formaat.", "Person": "Persoon", "OptionForceRemoteSourceTranscoding": "Forceer het transcoderen van op afstand bediende media bronnen (zoals LiveTV)", "NoCreatedLibraries": "Het lijkt erop dat er geen bibliotheek is gecreëerd. {0}Wilt u er nu een aanmaken?{1}", From c88345239525e012f48f6f4f0aa4832d842ab486 Mon Sep 17 00:00:00 2001 From: Cameron Date: Wed, 5 Aug 2020 20:22:48 +0100 Subject: [PATCH 45/56] add default --- src/plugins/chromecastPlayer/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/chromecastPlayer/plugin.js b/src/plugins/chromecastPlayer/plugin.js index 3d49f6fff6..22b49d6faf 100644 --- a/src/plugins/chromecastPlayer/plugin.js +++ b/src/plugins/chromecastPlayer/plugin.js @@ -577,7 +577,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', ' this.isLocalPlayer = false; this.lastPlayerData = {}; - new castSenderApiLoader().load().then(initializeChromecast.bind(this)); + new castSenderApiLoader.default().load().then(initializeChromecast.bind(this)); } ChromecastPlayer.prototype.tryPair = function (target) { From 6af88a366230a958340193b72bcf7320df7e575e Mon Sep 17 00:00:00 2001 From: sharkykh Date: Wed, 5 Aug 2020 18:28:45 +0000 Subject: [PATCH 46/56] Translated using Weblate (Hebrew) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/he/ --- src/strings/he.json | 84 +++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/src/strings/he.json b/src/strings/he.json index ae274c26c8..a063f59b76 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -10,7 +10,7 @@ "AllEpisodes": "כל הפרקים", "AllLibraries": "כל הספריות", "Anytime": "בכל עת", - "AroundTime": "בסביבות {0}", + "AroundTime": "בסביבות", "AsManyAsPossible": "כמה שיותר", "AttributeNew": "חדש", "Backdrops": "תמונות רקע", @@ -32,13 +32,13 @@ "ButtonRefreshGuideData": "רענן את מדריך השידור", "ButtonRemove": "הסר", "ButtonResetPassword": "איפוס סיסמא", - "ButtonRestart": "איתחול", + "ButtonRestart": "הפעל מחדש", "ButtonSave": "שמור", "ButtonSearch": "חיפוש", "ButtonSelectDirectory": "בחר תיקיות", "ButtonShutdown": "כבה", "ButtonSignIn": "היכנס", - "ButtonSignOut": "Sign out", + "ButtonSignOut": "התנתק", "ButtonSort": "מיין", "CancelRecording": "ביטול הקלטה", "CancelSeries": "בטל סדרה", @@ -114,11 +114,11 @@ "HeaderLatestRecordings": "הקלטות אחרונות", "HeaderLiveTV": "שידורים חיים", "HeaderMediaFolders": "ספריות מדיה", - "HeaderMetadataSettings": "הגדרות מטא נתונים", + "HeaderMetadataSettings": "הגדרות מטא-דאטה", "HeaderMovies": "סרטים", "HeaderMusicVideos": "קליפים", - "HeaderMyMedia": "הספרייה שלי", - "HeaderNextUp": "הבא", + "HeaderMyMedia": "המדיה שלי", + "HeaderNextUp": "הבא בתור", "HeaderPaths": "נתיבים", "HeaderPlayAll": "נגן הכל", "HeaderPleaseSignIn": "אנא היכנס", @@ -138,7 +138,7 @@ "Help": "עזרה", "Identify": "לזהות", "Images": "תמונות", - "InstallingPackage": "מתקין {0}", + "InstallingPackage": "מתקין {0} (גירסה {1})", "InstantMix": "מיקס מיידי", "ItemCount": "פריטים {0}", "Kids": "ילדים", @@ -151,11 +151,11 @@ "LabelAlbum": "אלבום:", "LabelAlbumArtists": "אלבום אומנים:", "LabelArtists": "אומנים:", - "LabelArtistsHelp": "הפרד מרובים באמצעות;", + "LabelArtistsHelp": "הפרד אמנים מרובים באמצעות נקודה-פסיק (;).", "LabelAudioLanguagePreference": "שפת קול מועדפת:", "LabelBirthDate": "תאריך לידה:", "LabelBirthYear": "שנת לידה:", - "LabelBlastMessageInterval": "אינטרוול הודעות דחיפה (בשניות)", + "LabelBlastMessageInterval": "תדירות הודעות דחיפה", "LabelBlastMessageIntervalHelp": "מגדיר את משך הזמן בשניות בין הודעות דחיפה של השרת.", "LabelCachePath": "נתיב cache:", "LabelChannels": "ערוצים:", @@ -165,7 +165,7 @@ "LabelCountry": "מדינה:", "LabelCriticRating": "דירוג ביקורת:", "LabelCurrentPassword": "סיסמא נוכחית:", - "LabelCustomCss": "CSS מותאם אישית", + "LabelCustomCss": "CSS מותאם אישית:", "LabelCustomRating": "דירוג מותאם אישית:", "LabelDateAdded": "תאריך הוסף:", "LabelDay": "יום:", @@ -175,15 +175,15 @@ "LabelDiscNumber": "מספר דיסק:", "LabelDisplayMissingEpisodesWithinSeasons": "הצג פרקים חסרים בתוך העונות", "LabelDisplayOrder": "סדר תצוגה:", - "LabelDownMixAudioScaleHelp": "הגבר אודיו כאשר הוא ממוזג. הגדר ל-1 לשמור על ערך הווליום המקורי", + "LabelDownMixAudioScaleHelp": "הגבר את עוצמת השמע כאשר הוא ממוזג. ערך השווה ל-1 יישמר את העוצמה המקורית.", "LabelDynamicExternalId": "{0} תעודת זהות:", "LabelEnableBlastAliveMessages": "הודעות דחיפה", "LabelEnableBlastAliveMessagesHelp": "אפשר זאת אם השרת לא מזוהה כאמין על ידי מכשירי UPnP אחרים ברשת שלך.", - "LabelEnableDlnaClientDiscoveryInterval": "זמן גילוי קליינטים (בשניות)", + "LabelEnableDlnaClientDiscoveryInterval": "זמן גילוי קליינטים", "LabelEnableDlnaDebugLogging": "אפשר ניהול רישום באגים בDLNA", "LabelEnableDlnaDebugLoggingHelp": "אפשרות זו תיצור קבצי לוג גדולים יותר ועליך להשתמש בה רק על מנת לפתור תקלות.", "LabelEnableDlnaPlayTo": "מאפשר ניגון DLNA ל", - "LabelEnableDlnaServer": "אפשר שרת Dina", + "LabelEnableDlnaServer": "אפשר שרת DLNA", "LabelEnableRealtimeMonitor": "אפשר מעקב בזמן אמת", "LabelEnableRealtimeMonitorHelp": "שינויים יעשו באופן מיידית על מערכות קבצים נתמכות.", "LabelEndDate": "תאריך סיום:", @@ -195,21 +195,21 @@ "LabelServerNameHelp": "השם יתן לזיהוי השרת. אם מושאר ריק, שם השרת יהיה שם המחשב.", "LabelKeepUpTo": "שמור עד ל:", "LabelLanguage": "שפה:", - "LabelLocalHttpServerPortNumber": "מספר פורט HTTP מקומי", + "LabelLocalHttpServerPortNumber": "מספר פורט HTTP מקומי:", "LabelLockItemToPreventChanges": "נעל פריט זה כדי למנוע שינויים עתידיים", "LabelMaxBackdropsPerItem": "מספר תמונות רקע מקסימאלי לפריט:", "LabelMaxParentalRating": "דירוג הורים מקסימאלי:", - "LabelMaxResumePercentage": "אחוזי המשכה מקסימאלים", - "LabelMaxResumePercentageHelp": "קובץ מוגדר כנוגן במלואו אם נעצר אחרי הזמן הזה", + "LabelMaxResumePercentage": "אחוזי המשכה מקסימאלים:", + "LabelMaxResumePercentageHelp": "קובץ מוגדר כנוגן במלואו אם נעצר אחרי הזמן הזה.", "LabelMaxScreenshotsPerItem": "מספר תמונות מסך מקסימאלי לפריט:", "LabelMessageTitle": "כותרת הודעה:", "LabelMetadataDownloadLanguage": "שפת הורדה מועדפת:", "LabelMetadataPath": "נתיב Metadata:", "LabelMinBackdropDownloadWidth": "רוחב תמונת רקע מינימאלי להורדה:", - "LabelMinResumeDuration": "משך המשכה מינימאלי (בשניות):", + "LabelMinResumeDuration": "משך המשכה מינימאלי:", "LabelMinResumeDurationHelp": "קובץ קצר מזה לא יהיה ניתן להמשך ניגון מנקודת העצירה", "LabelMinResumePercentage": "אחוזי המשכה מינימאלים:", - "LabelMinResumePercentageHelp": "כותרים יוצגו כלא נוגנו אם נצרו לפני הזמן הזה", + "LabelMinResumePercentageHelp": "כותרים יוצגו כלא נוגנו אם נצרו לפני הזמן הזה.", "LabelMinScreenshotDownloadWidth": "רחוב תמונת מסך מינימאלית להורדה:", "LabelMonitorUsers": "עקוב אחר פעילות מ:", "LabelName": "שם:", @@ -237,12 +237,12 @@ "LabelProfileAudioCodecs": "מקודדי שמע:", "LabelProfileCodecs": "מקודדים:", "LabelProfileVideoCodecs": "‮מקודדי וידאו:", - "LabelPublicHttpPort": "מספר פורט HTTP פומבי", + "LabelPublicHttpPort": "מספר פורט HTTP פומבי:", "LabelReadHowYouCanContribute": "למד איך אתה יכול לתרום.", "LabelRecord": "הקלטה:", "LabelRefreshMode": "מצב רענון:", "LabelReleaseDate": "תאריך הוצאה:", - "LabelRuntimeMinutes": "זמן ריצה (דקות):", + "LabelRuntimeMinutes": "זמן ריצה:", "LabelSaveLocalMetadata": "שמור תמונות רקע בתוך ספריות המדיה", "LabelSaveLocalMetadataHelp": "שמירת תמונות רקע בתוך ספריות המדיה תשים אותם במקום שבו יהיה קל לערוך אותם.", "LabelSeasonNumber": "מספר עונה:", @@ -264,7 +264,7 @@ "LabelUserLibrary": "ספריית משתמש:", "LabelYear": "שנה:", "LabelYoureDone": "סיימת!", - "LibraryAccessHelp": "בחר את ספריות המדיה אשר ישותפו עם המשתמש. מנהלים יוכלו לערות את כל התיקיות באמצעות עורך המידע.", + "LibraryAccessHelp": "בחר את הספריות אשר ישותפו עם המשתמש. מנהלים יוכלו לערות את כל התיקיות באמצעות עורך המידע.", "Like": "אוהב", "Live": "שידור חי", "LiveBroadcasts": "שידורים חיים", @@ -319,7 +319,7 @@ "OptionDatePlayed": "תאריך ניגון", "OptionDescending": "סדר יורד", "OptionDisableUser": "בטל משתמש זה", - "OptionDisableUserHelp": "אם מבוטל, השרת שלא יאפשר חיבורים ממשתמש זה. חיבורים פעילים יבוטלו מייד.", + "OptionDisableUserHelp": "השרת לא יאפשר חיבורים ממשתמש זה. חיבורים פעילים יבוטלו מייד.", "OptionDislikes": "לא אוהב", "OptionDownloadArtImage": "עטיפה", "OptionDownloadBackImage": "גב", @@ -344,7 +344,7 @@ "OptionMissingEpisode": "פרקים חסרים", "OptionMonday": "שני", "OptionNameSort": "שם", - "OptionNew": "חדש...", + "OptionNew": "חדש…", "OptionOnAppStartup": "בהפעלת התוכנה", "OptionOnInterval": "כל פרק זמן", "OptionParentalRating": "דירוג בקרת הורים", @@ -363,7 +363,7 @@ "OptionThursday": "חמישי", "OptionTrackName": "שם השיר", "OptionTuesday": "שלישי", - "OptionTvdbRating": "דירוג Tvdb", + "OptionTvdbRating": "דירוג TVDB", "OptionUnairedEpisode": "פרקים שלא שודרו", "OptionUnplayed": "לא נוגן", "OptionWakeFromSleep": "הער ממצב שינה", @@ -371,8 +371,8 @@ "OptionWeekly": "שבועי", "OriginalAirDateValue": "תאריך אוויר מקורי: {0}", "Overview": "סקירה כללית", - "PackageInstallCancelled": "{0} ההתקנה בוטלה.", - "PackageInstallFailed": "ההתקנה {0} נכשלה.", + "PackageInstallCancelled": "ההתקנה של {0} (גירסה {1}) בוטלה.", + "PackageInstallFailed": "ההתקנה של {0} (גירסה {1}) נכשלה.", "ParentalRating": "דירוג ההורים", "PasswordMatchError": "הסיסמא ואימות הסיסמא צריכות להיות זהות.", "PasswordResetComplete": "הסיסמא אופסה.", @@ -395,7 +395,7 @@ "RecordingCancelled": "הקלטה בוטלה.", "RecordingScheduled": "ההקלטה מתוזמנת.", "Refresh": "רענון", - "RefreshDialogHelp": "המטא נתונים מתרעננים על סמך הגדרות ושירותי אינטרנט שמופעלים בלוח המחוונים של מרכז אמבי.", + "RefreshDialogHelp": "המטא-דאטה מתרעננת על סמך הגדרות ושירותי אינטרנט שמופעלים בלוח הבקרה.", "RefreshQueued": "רענן תור.", "ReleaseDate": "תאריך שיחרור", "RemoveFromCollection": "הסר מאוספים", @@ -514,8 +514,8 @@ "AllLanguages": "כל השפות", "Alerts": "התראות", "Box": "מארז", - "BirthPlaceValue": "מיקום לידה: {0}", - "BirthDateValue": "תאריך לידה: {0}", + "BirthPlaceValue": "מקום לידה: {0}", + "BirthDateValue": "נולד: {0}", "Backdrop": "רקע", "AuthProviderHelp": "בחר ספק אימות שישמש לאימות הסיסמה של משתמש זה.", "Audio": "שמע", @@ -530,10 +530,10 @@ "Yesterday": "אתמול", "HeaderAlbumArtists": "אמני האלבום", "Favorites": "מועדפים", - "HeaderFavoriteAlbums": "אלבומים שאהבתי", + "HeaderFavoriteAlbums": "אלבומים מועדפים", "HeaderFavoriteArtists": "אמנים מועדפים", "Folders": "תיקיות", - "HeaderFavoriteShows": "סדרות מועדפות", + "HeaderFavoriteShows": "תוכניות מועדפות", "HeaderFavoriteEpisodes": "פרקים מועדפים", "HeaderFavoriteSongs": "שירים מועדפים", "Collections": "אוספים", @@ -541,7 +541,7 @@ "HeaderContinueWatching": "המשך לצפות", "AllowOnTheFlySubtitleExtraction": "אפשר חילוץ כתוביות בזמן אמת", "AllowHWTranscodingHelp": "אפשר למלקט לקודד הזרמות בזמן אמת. זה עשוי לעזור בהפחתת הקידוד שנעשה ע\"י השרת.", - "AllComplexFormats": "כל הפורמטים המורכבים (ASS, SSA, VOBSUB, PGS, SUB/IDX)", + "AllComplexFormats": "כל הפורמטים המורכבים (ASS, SSA, VOBSUB, PGS, SUB/IDX, …)", "Songs": "שירים", "Shows": "סדרות", "DownloadsValue": "{0} הורדות", @@ -601,7 +601,7 @@ "HeaderRestart": "הפעלה מחדש", "HeaderProfileInformation": "מידע פרופיל", "HeaderProfile": "פרופיל", - "HeaderPreferredMetadataLanguage": "שפת מטא-נתונים מועדפת", + "HeaderPreferredMetadataLanguage": "שפת מטא-דאטה מועדפת", "HeaderPluginInstallation": "התקנת תוסף", "HeaderPlayOn": "נגן על", "HeaderPinCodeReset": "איפוס קוד סיכה", @@ -677,7 +677,7 @@ "EnableExternalVideoPlayers": "נגני וידאו חיצוניים", "EnableCinemaMode": "מצב קולנוע", "EnableBackdrops": "תמונות רקע", - "EditMetadata": "ערוך מטא-נתונים", + "EditMetadata": "ערוך מטא-דאטה", "DrmChannelsNotImported": "‫ערוצים בעלי ניהול זכויות דיגיטלי (DRM) לא ייובאו.", "Down": "למטה", "Display": "תצוגה", @@ -726,7 +726,7 @@ "ButtonAddScheduledTaskTrigger": "הוסף טריגר", "Browse": "עיין", "BoxRear": "מארז (מאחור)", - "BookLibraryHelp": "ניתן להוסיף ספרים מוקלטים וספרים כתובים. עיינו {0}במדריך מתן שמות לספרים{1}.", + "BookLibraryHelp": "ניתן להוסיף ספרים מוקלטים וספרים כתובים. עיינו {0} במדריך מתן שמות לספרים {1}.", "Desktop": "שולחן עבודה", "MessageDeleteTaskTrigger": "האם אתה בטוח שברצונך למחוק את מפעיל המשימה הזה?", "LastSeen": "נראה לאחרונה ב-{0}", @@ -738,11 +738,11 @@ "DeleteDeviceConfirmation": "האם אתה בטוח שברצונך למחוק את המכשיר? הוא יופיע שוב בפעם הבאה שמשתמש ייכנס באמצעותו.", "ColorSpace": "מרחב צבע", "CinemaModeConfigurationHelp": "מצב קולנוע מביא את חוויית הקולנוע היישר אל הסלון עם האפשרות להפעיל טריילרים וקדימונים מותאמים אישית לפני הסרט.", - "ChannelAccessHelp": "בחר את הערוצים לשיתוף עם משתמש זה. מנהלים יוכלו לערוך את כל הערוצים בעזרת \"מנהל המטא-דאטה\".", + "ChannelAccessHelp": "בחר את הערוצים לשיתוף עם משתמש זה. מנהלים יוכלו לערוך את כל הערוצים בעזרת מנהל המטא-דאטה.", "ButtonResetEasyPassword": "אתחל קוד פין פשוט", "ButtonOff": "כיבוי", "ButtonLibraryAccess": "הרשאות גישה לספרייה", - "BurnSubtitlesHelp": "מחליט אם על השרת לצרוב כתוביות בזמן קידוד וידאו. הימנעות מכך תשפר מאוד את הביצועים. בחר \"אוטומטי\" לצריבת כתוביות על בסיס פורמט תמונה (VOBSUB, PGS, SUB, IDX) וכתוביות ASS או SSA מסויימות.", + "BurnSubtitlesHelp": "מחליט אם על השרת לצרוב כתוביות בזמן קידוד וידאו. הימנעות מכך תשפר מאוד את הביצועים. בחר \"אוטומטי\" לצריבת כתוביות על בסיס פורמט תמונה (VOBSUB, PGS, SUB, IDX, …) וכתוביות ASS או SSA מסויימות.", "Artist": "אמן", "AllowedRemoteAddressesHelp": "רשימת IP \\ מיסוך רשת המופרדת בפסיקים עבור רשתות שיורשו להתחבר מרחוק. במידה ותישאר ריקה, כל הכתובות יורשו להתחבר.", "Album": "אלבום", @@ -764,5 +764,13 @@ "DashboardServerName": "שרת: {0}", "DashboardVersionNumber": "גירסה: {0}", "DashboardArchitecture": "ארכיטקטורה: {0}", - "DashboardOperatingSystem": "מערכת הפעלה: {0}" + "DashboardOperatingSystem": "מערכת הפעלה: {0}", + "HeaderMyMediaSmall": "המדיה שלי (קטן)", + "HeaderMusicQuality": "איכות מוזיקה", + "HeaderMediaInfo": "מידע על המדיה", + "HeaderMoreLikeThis": "עוד כמו זה", + "HeaderMedia": "מדיה", + "LabelMetadata": "מטא-דאטה:", + "HeaderSelectMetadataPath": "בחר נתיב מטא-דאטה", + "NextUp": "הבא בתור" } From 73e8b5039527bd0c7b23571bed3dff73c9c2a640 Mon Sep 17 00:00:00 2001 From: sharkykh Date: Wed, 5 Aug 2020 19:38:19 +0000 Subject: [PATCH 47/56] Translated using Weblate (Hebrew) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/he/ --- src/strings/he.json | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/strings/he.json b/src/strings/he.json index a063f59b76..9155e310a3 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -772,5 +772,23 @@ "HeaderMedia": "מדיה", "LabelMetadata": "מטא-דאטה:", "HeaderSelectMetadataPath": "בחר נתיב מטא-דאטה", - "NextUp": "הבא בתור" + "NextUp": "הבא בתור", + "LabelBaseUrl": "כתובת בסיס:", + "LabelEnableHttpsHelp": "האזן על גבי פורט ה-HTTPS המוגדר. חובה לספק תעודה תקינה על מנת שהגדרה זו תכנס לתוקף.", + "LabelEnableHttps": "הפעל HTTPS", + "LabelEnableHardwareDecodingFor": "הפעל פענוח חומרה עבור:", + "LabelEnableDlnaServerHelp": "אפשר למכשירי UPnP ברשת שלך לעיין בתוכן ולנגן אותו.", + "LabelEnableAutomaticPortMap": "הפעל מיפוי פורט אוטומטי", + "LabelDropImageHere": "גרור תמונה לכאן, או לחץ כדי לעיין.", + "LabelDownloadLanguages": "הורד שפות:", + "LabelDownMixAudioScale": "הגברת עוצמת שמע כאשר הוא ממוזג:", + "LabelDisplaySpecialsWithinSeasons": "הצג פרקים מיוחדים בתוך העונות שבמהלכן הם שודרו", + "LabelDisplayName": "שם תצוגה:", + "LabelDisplayMode": "מצב תצוגה:", + "LabelDisplayLanguageHelp": "תרגום Jellyfin הוא פרויקט מתמשך.", + "LabelDisplayLanguage": "שפת תצוגה:", + "LabelDidlMode": "מצב DIDL:", + "LabelDeviceDescription": "תיאור מכשיר", + "LabelDefaultScreen": "מסך ברירת-מחדל:", + "LabelCustomDeviceDisplayName": "שם תצוגה:" } From c73a2d83761e480c7b1dce88ddb717147458d9a4 Mon Sep 17 00:00:00 2001 From: sharkykh Date: Wed, 5 Aug 2020 19:51:52 +0000 Subject: [PATCH 48/56] Translated using Weblate (Hebrew) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/he/ --- src/strings/he.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/strings/he.json b/src/strings/he.json index 9155e310a3..c61bfe9e1a 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -790,5 +790,15 @@ "LabelDidlMode": "מצב DIDL:", "LabelDeviceDescription": "תיאור מכשיר", "LabelDefaultScreen": "מסך ברירת-מחדל:", - "LabelCustomDeviceDisplayName": "שם תצוגה:" + "LabelCustomDeviceDisplayName": "שם תצוגה:", + "LabelImageType": "סוג תמונה:", + "LabelHttpsPortHelp": "מספר פורט ה-TCP עבור שרת ה-HTTPS.", + "LabelHttpsPort": "מספר פורט HTTPS מקומי:", + "LabelGroupMoviesIntoCollections": "אגד סרטים לתוך אוספים", + "LabelFriendlyName": "שם ידידותי:", + "LabelFormat": "תבנית:", + "LabelForgotPasswordUsernameHelp": "הכנס/י את שם המשתמש שלך, אם את/ה זוכר/ת אותו.", + "LabelFont": "גופן:", + "LabelFolder": "תיקייה:", + "LabelFileOrUrl": "קובץ או כתובת אינטרנט:" } From 98481fc4502abe3fe5864a8dfc07f93108840b80 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Wed, 5 Aug 2020 21:26:05 +0000 Subject: [PATCH 49/56] Translated using Weblate (Russian) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/ru/ --- src/strings/ru.json | 75 +++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/src/strings/ru.json b/src/strings/ru.json index 9089e4bea7..24d5cdd90f 100644 --- a/src/strings/ru.json +++ b/src/strings/ru.json @@ -175,8 +175,8 @@ "DetectingDevices": "Обнаруживются устройства", "DeviceAccessHelp": "Это относится только к устройствам, которые могут быть однозначно распознаны и не препятствует доступу через браузер. Фильтрация доступа пользовательского устройства запретит использование новых устройств до тех пор, пока они не будут одобрены.", "DirectPlaying": "Воспроизводится напрямую", - "DirectStreamHelp1": "Медиаданные совместимы с устройством в отношении разрешения и типа медиаданных (H.264, AC3, и т.д.), но в несовместимом файловом контейнере (mkv, avi, wmv и т.д.). Видео будет повторно упаковано динамически перед его трансляцией на устройство.", - "DirectStreamHelp2": "При прямой трансляции файла расходуется очень мало вычислительной мощности без потери качества видео.", + "DirectStreamHelp1": "Медиаданные совместимы с устройством в отношении разрешения и типа медиаданных (H.264, AC3, и т.д.), но в несовместимом файловом контейнере (mkv, avi, wmv и т.д.). Видео будет повторно упаковано динамически перед его отправлением на устройство.", + "DirectStreamHelp2": "Прямая трансляции расходует очень мало вычислительной мощности с минимальной потерей качества видео.", "DirectStreaming": "Транслируется напрямую", "Director": "Режиссёр", "Directors": "Режиссёры", @@ -287,7 +287,7 @@ "HeaderAllowMediaDeletionFrom": "Разрешить удаление медиаданных из", "HeaderApiKey": "API-ключ", "HeaderApiKeys": "API-ключи", - "HeaderApiKeysHelp": "Внешним приложениям требуется API-ключ для того, чтобы подключиться к Jellyfin Server. Ключи выдаются при входе с учётной записью Jellyfin или ключ предоставляется приложению вручную.", + "HeaderApiKeysHelp": "Внешним приложениям требуется API-ключ для того, чтобы подключиться к серверу. Ключи выдаются при входе с учётной записью обычного пользователя или ключ предоставляется приложению вручную.", "HeaderApp": "Приложение", "HeaderAppearsOn": "Фигурирует в", "HeaderAudioBooks": "Аудиокниги", @@ -359,7 +359,7 @@ "HeaderItems": "Элементы", "HeaderKeepRecording": "Хранение записи", "HeaderKeepSeries": "Хранение сериала", - "HeaderKodiMetadataHelp": "Для включения или отключения NFO-метаданных, начните править медиатеку в области настройки медиатек и найдите раздел хранителей метаданных.", + "HeaderKodiMetadataHelp": "Для включения или отключения NFO-метаданных, правьте медиатеку и найдите раздел хранителей метаданных.", "HeaderLatestEpisodes": "Новейшие эпизоды", "HeaderLatestMedia": "Новейшие медиаданные", "HeaderLatestMovies": "Новейшие фильмы", @@ -408,7 +408,7 @@ "HeaderPreferredMetadataLanguage": "Выбор языка метаданных", "HeaderProfile": "Профиль", "HeaderProfileInformation": "О профиле", - "HeaderProfileServerSettingsHelp": "Данные значения управляют тем, как Jellyfin Server будет представляться устройству.", + "HeaderProfileServerSettingsHelp": "Данные значения управляют тем, как сервер будет представлять себя клиентам.", "HeaderRecentlyPlayed": "Воспроизведённые недавно", "HeaderRecordingOptions": "Опции записи", "HeaderRecordingPostProcessing": "Постобработка записи", @@ -426,13 +426,13 @@ "HeaderSecondsValue": "{0} с", "HeaderSelectCertificatePath": "Выбор пути к сертификату", "HeaderSelectMetadataPath": "Выбор пути для метаданных", - "HeaderSelectMetadataPathHelp": "Найдите или введите путь, в пределах которого хотите хранить метаданные. Папка должна быть доступна для записи.", + "HeaderSelectMetadataPathHelp": "Найдите или введите путь, который хотите использовать для метаданныхе. Папка должна быть доступна для записи.", "HeaderSelectPath": "Выбор пути", "HeaderSelectServer": "Выбор сервера", "HeaderSelectServerCachePath": "Выбор пути для серверного кэша", "HeaderSelectServerCachePathHelp": "Найдите или введите путь, чтобы использовать для файлов серверного кэша. Папка должна быть доступна для записи.", "HeaderSelectTranscodingPath": "Выбор пути для временных файлов перекодировки", - "HeaderSelectTranscodingPathHelp": "Найдите или введите путь, чтобы использовать для временных файлов перекодировки. Папка должна быть доступна для записи.", + "HeaderSelectTranscodingPathHelp": "Найдите или введите путь, чтобы использовать для файлов перекодировки. Папка должна быть доступна для записи.", "HeaderSendMessage": "Передача сообщения", "HeaderSeries": "Сериалы", "HeaderSeriesOptions": "Опции сериала", @@ -485,8 +485,8 @@ "HttpsRequiresCert": "Чтобы включить HTTPS для внешних подключений, вам нужно будет предоставить доверенный SSL-cертификат, например, Let's Encrypt. Предоставьте сертификат или отключите защищенные соединения.", "Identify": "Распознать", "Images": "Изображения", - "ImportFavoriteChannelsHelp": "При включении, будут импортированы только каналы, которые обозначены как избранное на тюнерном устройстве.", - "ImportMissingEpisodesHelp": "При включении, информация об отсутствующих эпизодах будет импортирована в вашу базу данных Jellyfin и отображаться в пределах сезонов и сериалов. Это может увеличить время сканирования медиатеки.", + "ImportFavoriteChannelsHelp": "Будут импортированы только каналы, которые обозначены как избранное на тюнерном устройстве.", + "ImportMissingEpisodesHelp": "Информация об отсутствующих эпизодах будет импортирована в вашу базу данных и отображена в пределах сезонов и сериалов. Это может заметно увеличить время сканирования медиатеки.", "InstallingPackage": "Устанавливается {0} (версия {1})", "InstantMix": "Автомикс", "ItemCount": "{0} элемент(а/ов)", @@ -517,15 +517,15 @@ "LabelAppName": "Название приложения", "LabelAppNameExample": "Пример: Sickbeard, Sonarr", "LabelArtists": "Исполнители:", - "LabelArtistsHelp": "Для разделения используйте точку с запятой ;", + "LabelArtistsHelp": "Для разделения исполнителей используйте точку с запятой ;", "LabelAudio": "Аудио", "LabelAudioLanguagePreference": "Выбор языка аудио:", "LabelAutomaticallyRefreshInternetMetadataEvery": "Автоматически обновлять метаданные из Интернета:", "LabelBindToLocalNetworkAddress": "Привязка к адресу в локальной сети:", - "LabelBindToLocalNetworkAddressHelp": "Необязательно. Переопределяется локальный IP-адрес для привязки HTTP-сервера. Если поле пусто, то привязка сервера будет ко всем доступным адресам. При изменении данного значения потребуется перезапуск Jellyfin Server.", + "LabelBindToLocalNetworkAddressHelp": "Переопределяется локальный IP-адрес для HTTP-сервера. Если поле пусто, то привязка сервера будет ко всем доступным адресам. При изменении данного значения потребуется перезапуск Jellyfin Server.", "LabelBirthDate": "Дата рождения:", "LabelBirthYear": "Год рождения:", - "LabelBlastMessageInterval": "Интервал сообщений проверки активности, с", + "LabelBlastMessageInterval": "Интервал сообщений проверки активности", "LabelBlastMessageIntervalHelp": "Определяет длительность в секундах между бомбардированием сообщениями проверки активности.", "LabelBlockContentWithTags": "Блокирование элементов с тегами:", "LabelBurnSubtitles": "Внедрение субтитров:", @@ -545,7 +545,7 @@ "LabelCustomCertificatePath": "Путь к пользовательскому SSL-сертификату:", "LabelCustomCertificatePathHelp": "Путь к файлу PKCS #12, содержащему сертификат и \tзакрытый ключ для включения поддержки TLS на произвольном домене.", "LabelCustomCss": "Настраиваемые CSS:", - "LabelCustomCssHelp": "Применяйте свою собственную настраиваемую стилизацию к веб-интерфейсу.", + "LabelCustomCssHelp": "Применяйте свои собственные настраиваемые стили в веб-интерфейсе.", "LabelCustomDeviceDisplayName": "Отображаемое название:", "LabelCustomDeviceDisplayNameHelp": "Приведите произвольное имя для отображения или не заполняйте, чтобы использовать имя, выданное устройством.", "LabelCustomRating": "Произвольная возрастная категория:", @@ -585,7 +585,7 @@ "LabelEnableDlnaDebugLogging": "Включить журналирование отладки DLNA", "LabelEnableDlnaDebugLoggingHelp": "Создаются большие файлы Журнала, рекомендуется использовать только для поиска неполадок.", "LabelEnableDlnaPlayTo": "Включить DLNA-функцию Воспроизвести На", - "LabelEnableDlnaPlayToHelp": "Обнаруживаются устройства внутри своей сети, а также предоставляется возможность удалённо управлять ими.", + "LabelEnableDlnaPlayToHelp": "Обнаруживаются устройства внутри своей сети, а также предоставляется возможность управлять ими удалённо.", "LabelEnableDlnaServer": "Включить DLNA-сервер", "LabelEnableDlnaServerHelp": "Для UPnP-устройств домашней сети возможна навигация по содержанию и его воспроизведение.", "LabelEnableHardwareDecodingFor": "Включить аппаратное декодирование для:", @@ -606,9 +606,9 @@ "LabelForgotPasswordUsernameHelp": "Введите имя пользователя, если помните его.", "LabelFormat": "Формат:", "LabelFriendlyName": "Понятное имя:", - "LabelServerNameHelp": "Это имя используется для распознавания сервера и будет по умолчанию именем компьютера.", + "LabelServerNameHelp": "Это имя используется для распознавания сервера и будет по умолчанию именем хоста сервера.", "LabelGroupMoviesIntoCollections": "Группировать фильмы внутрь коллекций", - "LabelGroupMoviesIntoCollectionsHelp": "При отображении списка фильмов, элементы, принадлежащие к одной коллекции будут отображаться как единый сгруппированный элемент.", + "LabelGroupMoviesIntoCollectionsHelp": "При отображении списков фильмов, фильмы из коллекции будут отображаться как единый группированный элемент.", "LabelH264Crf": "Значение CRF H264-кодирования:", "LabelEncoderPreset": "Предустановка H264-кодирования:", "LabelHardwareAccelerationType": "Аппаратное ускорение:", @@ -616,7 +616,7 @@ "LabelHomeNetworkQuality": "Качество в домашней сети:", "LabelHomeScreenSectionValue": "Главная страница - раздел {0}:", "LabelHttpsPort": "Номер локального HTTPS-порта:", - "LabelHttpsPortHelp": "TCP-порт, ко которому следует создать привязку HTTPS-сервера Jellyfin.", + "LabelHttpsPortHelp": "Номер TCP-порта для HTTPS-сервера.", "LabelIconMaxHeight": "Макс. высота значка:", "LabelIconMaxHeightHelp": "Максимальное разрешение значков представляемых с помощью upnp:icon.", "LabelIconMaxWidth": "Макс. ширина значка:", @@ -644,7 +644,7 @@ "LabelLanguage": "Язык:", "LabelLineup": "Список сопоставления:", "LabelLocalHttpServerPortNumber": "Номер локального HTTP-порта:", - "LabelLocalHttpServerPortNumberHelp": "TCP-порт, ко которому следует создать привязку HTTP-сервера Jellyfin.", + "LabelLocalHttpServerPortNumberHelp": "Номер TCP-порта для HTTP-сервера.", "LabelLockItemToPreventChanges": "Зафиксировать данный элемент, чтобы запретить будущие правки", "LabelLoginDisclaimer": "Предупреждение при входе:", "LabelLoginDisclaimerHelp": "Сообщение будет отображаться в нижней части страницы входа в систему.", @@ -670,7 +670,7 @@ "LabelMetadataReaders": "Считыватели метаданных:", "LabelMetadataReadersHelp": "Ранжируйте предпочитаемые локальные источники метаданных в порядке приоритета. Будет считан первый же найденный файл.", "LabelMetadataSavers": "Хранители метаданных:", - "LabelMetadataSaversHelp": "Выберите форматы файлов, куда будут сохраняться метаданные.", + "LabelMetadataSaversHelp": "Выберите форматы файлов, которые будут использоваться при сохранении метаданных.", "LabelMethod": "Метод:", "LabelMinBackdropDownloadWidth": "Минимальная ширина загружаемого фона:", "LabelMinResumeDuration": "Минимальная длительность для возобновления:", @@ -686,7 +686,7 @@ "LabelMovieCategories": "Фильмовые категории:", "LabelMoviePrefix": "Префикс фильма:", "LabelMoviePrefixHelp": "При применении к названиям фильмов префикса, введите его здесь, чтобы он правильно обрабатывался на сервере.", - "LabelMovieRecordingPath": "Путь к записываемым фильмам (необязательно):", + "LabelMovieRecordingPath": "Путь к записываемым фильмам:", "LabelMusicStreamingTranscodingBitrate": "Битрейт перекодировки музыки:", "LabelMusicStreamingTranscodingBitrateHelp": "Укажите максимальный битрейт при трансляции музыки.", "LabelName": "Имя:", @@ -699,7 +699,7 @@ "LabelNumber": "Номер:", "LabelNumberOfGuideDays": "Число дней для загрузки данных телегида:", "LabelNumberOfGuideDaysHelp": "Больше дней загрузки данных телегида обеспечивает возможность заблаговременно назначать расписание и просматривать больше перечней, однако это займёт больше времени для загрузки. При значении «Авто» выбор определяется числом каналов.", - "LabelOptionalNetworkPath": "(Необязательно) Общедоступная сетевая папка:", + "LabelOptionalNetworkPath": "Общедоступная сетевая папка:", "LabelOptionalNetworkPathHelp": "Если данная папка является общей в сети, указание пути к сетевой папке может позволить Jellyfin-приложениям на других устройствах иметь прямой доступ к медиафайлам. Например, {0} или {1}.", "LabelOriginalAspectRatio": "Исходное соотношение сторон:", "LabelOriginalTitle": "Оригинальное название:", @@ -744,7 +744,7 @@ "LabelReleaseDate": "Дата выпуска:", "LabelRemoteClientBitrateLimit": "Ограничение битрейта интернет-трансляции, Мбит/с:", "LabelRemoteClientBitrateLimitHelp": "Необязательное ограничение битрейта для каждого из сетевых устройств. Может потребоваться, чтобы не допускать использования устройствами большего битрейта, чем способно пропустить интернет-соединение. Может привести к росту загрузки процессора на вашем сервере, так как потребуется динамическое перекодирование видео для снижения битрейта.", - "LabelRuntimeMinutes": "Длительность, мин:", + "LabelRuntimeMinutes": "Длительность:", "LabelSaveLocalMetadata": "Сохранять иллюстрации внутри медиапапок", "LabelSaveLocalMetadataHelp": "При сохранении иллюстраций внутри медиапапок, те помещаются в месте, где их можно легко править.", "LabelScheduledTaskLastRan": "Последний запуск был {0}, занял {1}.", @@ -756,7 +756,7 @@ "LabelSelectVersionToInstall": "Выбрать версию для установки:", "LabelSendNotificationToUsers": "Передача уведомления для:", "LabelSerialNumber": "Серийный номер", - "LabelSeriesRecordingPath": "Путь к записываемым сериалам (необязательно):", + "LabelSeriesRecordingPath": "Путь к записываемым сериалам:", "LabelServerHost": "Узел:", "LabelServerHostHelp": "192.168.1.100:8096 или https://myserver.com", "LabelSimultaneousConnectionLimit": "Лимит одновременных потоков:", @@ -917,7 +917,7 @@ "MessageYouHaveVersionInstalled": "В настоящее время установлена версия {0}.", "Metadata": "Метаданные", "MetadataManager": "Дисп. метаданных", - "MetadataSettingChangeHelp": "Изменение параметров метаданных повлияет на новое содержание, которое будет добавляться в дальнейшем. Чтобы обновить существующие содержание, откройте экран с подробностями и нажмите кнопку Обновить, или выполните массовое обновление, с помощью Диспетчера метаданных.", + "MetadataSettingChangeHelp": "Изменение параметров метаданных повлияет на новое содержание, добавляемое в будущем.. Чтобы обновить существующие содержание, откройте экран с подробностями и нажмите кнопку Обновить, или выполните массовое обновление, с помощью Диспетчера метаданных.", "MinutesAfter": "минут(у/ы) после", "MinutesBefore": "минут(у/ы) до", "Mobile": "Мобильный", @@ -966,7 +966,7 @@ "OptionAllowLinkSharingHelp": "Общедоступны только веб-страницы содержащие сведения о медиаданных. Медиафайлы никогда не предоставляются для общего просмотра. Совместно используемые ресурсы ограничены во времени, а срок действия истекает через {0} дн(я/ей).", "OptionAllowManageLiveTv": "Разрешить управление эфирными записями", "OptionAllowMediaPlayback": "Разрешить воспроизведение медиаданных", - "OptionAllowMediaPlaybackTranscodingHelp": "Ограничение доступа к перекодировке может привести к сбоям воспроизведения в Jellyfin-приложениях из-за неподдерживаемых форматов носителей.", + "OptionAllowMediaPlaybackTranscodingHelp": "Ограничение доступа к перекодировке может привести к сбоям воспроизведения в клиентах из-за неподдерживаемых форматов носителей.", "OptionAllowRemoteControlOthers": "Разрешить удалённое управление другими пользователями", "OptionAllowRemoteSharedDevices": "Разрешить удалённое управление используемыми совместно устройствами", "OptionAllowRemoteSharedDevicesHelp": "DLNA-устройства считаются используемыми совместно, пока какой-либо пользователь не начнёт управлять ими.", @@ -979,7 +979,7 @@ "OptionAuto": "Авто", "OptionAutomatic": "Авто", "OptionAutomaticallyGroupSeries": "Автоматически сливать вместе сериалы, которые разбросаны по нескольким папкам", - "OptionAutomaticallyGroupSeriesHelp": "При включении, сериалы, которые разбросаны по нескольким папкам данной медиатеки, будут автоматически слиты в единый сериал.", + "OptionAutomaticallyGroupSeriesHelp": "Части сериала, которые разбросаны по нескольким папкам данной медиатеки, будут автоматически слиты в единый сериал.", "OptionBlockBooks": "Книги", "OptionBlockChannelContent": "Содержание интернет-канала", "OptionBlockLiveTvChannels": "Эфирные каналы", @@ -999,7 +999,7 @@ "OptionDatePlayed": "Дата воспроизведения", "OptionDescending": "По убыванию", "OptionDisableUser": "Заблокировать пользователя", - "OptionDisableUserHelp": "При блокировании, этому пользователю не разрешаются любые подключения к серверу. Имеющиеся соединения будут разорваны.", + "OptionDisableUserHelp": "Этому пользователю не разрешаются любые подключения к серверу. Имеющиеся соединения будут разорваны.", "OptionDislikes": "Не нравящиеся", "OptionDisplayFolderView": "Отображать аспект Папки для просмотра обычных медиапапок", "OptionDisplayFolderViewHelp": "Отображение аспекта \"Папки\" рядом с другими вашими медиатеками. Это может быть полезно, если вы хотите вид обычных папок.", @@ -1009,7 +1009,7 @@ "OptionDownloadBoxImage": "DVD-бокс", "OptionDownloadDiscImage": "Диск", "OptionDownloadImagesInAdvance": "Загружать изображения заблаговременно", - "OptionDownloadImagesInAdvanceHelp": "По умолчанию, большинство изображений загружаются только при запросе от Jellyfin-приложения. Включите данную опцию, чтобы загружать все изображения заблаговременно, при импорте новых медиаданных. Это может привести к существенно длительным сканированиям медиатеки.", + "OptionDownloadImagesInAdvanceHelp": "По умолчанию, большинство изображений загружаются только при запросе от клиента. Включите данную опцию, чтобы загружать все изображения заблаговременно, при импорте новых медиаданных. Это может привести к существенно длительным сканированиям медиатеки.", "OptionDownloadLogoImage": "Логотип", "OptionDownloadMenuImage": "Меню", "OptionDownloadPrimaryImage": "Основной", @@ -1042,7 +1042,7 @@ "OptionHlsSegmentedSubtitles": "Сегмент. субтитры HLS", "OptionHomeVideos": "Фотографии", "OptionIgnoreTranscodeByteRangeRequests": "Игнорировать запросы диапазона байтов перекодировки", - "OptionIgnoreTranscodeByteRangeRequestsHelp": "При включении, эти запросы будут учтены, но заголовок диапазона байтов будет проигнорирован.", + "OptionIgnoreTranscodeByteRangeRequestsHelp": "Эти запросы будут учтены, но заголовок диапазона байтов будет проигнорирован.", "OptionImdbRating": "Оценка IMDb", "OptionLikes": "Нравящиеся", "OptionMax": "Макс.", @@ -1055,9 +1055,9 @@ "OptionOnInterval": "В интервале", "OptionParentalRating": "Возрастная категория", "OptionPlainStorageFolders": "Отображать все папки, как обычные папки хранения", - "OptionPlainStorageFoldersHelp": "При включении, все папки описываются в DIDL как «object.container.storageFolder», вместо более конкретного типа, например, «object.container.person.musicArtist».", + "OptionPlainStorageFoldersHelp": "Все папки описываются в DIDL как «object.container.storageFolder», вместо более специфичного типа, например, «object.container.person.musicArtist».", "OptionPlainVideoItems": "Отображать все видео, как обычные видео элементы", - "OptionPlainVideoItemsHelp": "При включении, все видео описываются в DIDL как «object.item.videoItem», вместо более конкретного типа, например, «object.item.videoItem.movie».", + "OptionPlainVideoItemsHelp": "Все видео описываются в DIDL как «object.item.videoItem», вместо более специфичного типа, например, «object.item.videoItem.movie».", "OptionPlayCount": "Кол. воспроизведений", "OptionPlayed": "Воспроизведённые", "OptionPremiereDate": "Дата премьеры", @@ -1148,7 +1148,7 @@ "RecordingScheduled": "Запись назначена.", "Recordings": "Записи", "Refresh": "Обновить", - "RefreshDialogHelp": "Обновление метаданных определяются параметрами и интернет-услугами, которые включены в Панели Jellyfin Server.", + "RefreshDialogHelp": "Обновление метаданных определяются параметрами и интернет-услугами, которые включены в Панели.", "RefreshMetadata": "Обновить метаданные", "RefreshQueued": "Обновление в очереди.", "ReleaseDate": "Дата выпуска", @@ -1395,11 +1395,11 @@ "OptionPosterCard": "Постер-карта", "OptionThumb": "Эскиз", "OptionThumbCard": "Эскиз-карта", - "PasswordResetProviderHelp": "Выберите поставщика сброса пароля, который будет использоваться, когда этот пользователь запрашивает сброс пароля", + "PasswordResetProviderHelp": "Выберите поставщика сброса пароля, который использовуется при запросе пользователем сброса пароля", "PlaybackData": "Данные воспроизведения", "SubtitleOffset": "Сдвиг субтитров", "TabNetworking": "Работа в сети", - "LabelBaseUrlHelp": "Добавляется пользовательский подкаталог к URL сервера. Например: http://example.com/<baseurl>", + "LabelBaseUrlHelp": "Добавляет пользовательский подкаталог к URL сервера. Например: http://example.com/<baseurl>", "LabelPlayer": "Проигрыватель:", "MoreMediaInfo": "О медиаданных", "LabelVideoCodec": "Видео кодек:", @@ -1472,7 +1472,7 @@ "UnsupportedPlayback": "Jellyfin не может расшифровать содержимое, защищенное DRM, но в любом случае будет предпринята попытка расшифровки всего содержимого, включая защищенные заголовки. Некоторые файлы могут выглядеть полностью черными из-за шифрования или других неподдерживаемых функций, таких как интерактивные заголовки.", "HeaderFavoritePlaylists": "Избранные плей-листы", "LabelRequireHttpsHelp": "Если этот флажок установлен, сервер будет автоматически перенаправлять все запросы через HTTP на HTTPS. Это не имеет никакого эффекта, если сервер не слушает HTTPS.", - "LabelEnableHttpsHelp": "Позволяет серверу слушать HTTPS-порт. Для работы необходим действующий сертификат.", + "LabelEnableHttpsHelp": "Прослушивается указанный HTTPS-порт. Чтобы это вступило в силу, также необходимо предоставить действительный сертификат.", "ApiKeysCaption": "Список действующих текущих API-ключей", "TabDVR": "DVR", "SaveChanges": "Сохранить изменения", @@ -1539,5 +1539,8 @@ "Writers": "Сценаристы", "ViewAlbumArtist": "Посмотреть альбом исполнителя", "ClearQueue": "Очистить очередь", - "ButtonPlayer": "Проигрыватель" + "ButtonPlayer": "Проигрыватель", + "PreviousTrack": "Перейти к предыдущему", + "NextTrack": "Перейти к следующему", + "LabelUnstable": "Нестабильная" } From 3680f478457f10acf2ee94d8c23c60b395b9a86e Mon Sep 17 00:00:00 2001 From: Cameron Date: Thu, 6 Aug 2020 09:46:23 +0100 Subject: [PATCH 50/56] Remove duplicates from package.json --- package.json | 7 ------- 1 file changed, 7 deletions(-) diff --git a/package.json b/package.json index ad4c8e1109..2ac1702d50 100644 --- a/package.json +++ b/package.json @@ -191,12 +191,6 @@ "src/controllers/music/musicplaylists.js", "src/controllers/music/musicrecommended.js", "src/controllers/music/songs.js", - "src/controllers/dashboard/plugins/repositories.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/dashboard/mediaLibrary.js", "src/controllers/dashboard/metadataImages.js", "src/controllers/dashboard/metadatanfo.js", @@ -218,7 +212,6 @@ "src/controllers/edititemmetadata.js", "src/controllers/favorites.js", "src/controllers/hometab.js", - "src/controllers/dashboard/plugins/repositories.js", "src/controllers/movies/moviecollections.js", "src/controllers/movies/moviegenres.js", "src/controllers/movies/movies.js", From d61fa6bdf654dbe68ae1b14d11341e09a0cab65e Mon Sep 17 00:00:00 2001 From: sharkykh Date: Thu, 6 Aug 2020 12:20:42 +0000 Subject: [PATCH 51/56] Translated using Weblate (Hebrew) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/he/ --- src/strings/he.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/strings/he.json b/src/strings/he.json index c61bfe9e1a..7c27d407c3 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -800,5 +800,6 @@ "LabelForgotPasswordUsernameHelp": "הכנס/י את שם המשתמש שלך, אם את/ה זוכר/ת אותו.", "LabelFont": "גופן:", "LabelFolder": "תיקייה:", - "LabelFileOrUrl": "קובץ או כתובת אינטרנט:" + "LabelFileOrUrl": "קובץ או כתובת אינטרנט:", + "Season": "עונה" } From 3204eefc5c8f9cf0dbe2bace960f8f6ef50a57cd Mon Sep 17 00:00:00 2001 From: sharkykh Date: Thu, 6 Aug 2020 12:26:20 +0000 Subject: [PATCH 52/56] Translated using Weblate (Hebrew) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/he/ --- src/strings/he.json | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/src/strings/he.json b/src/strings/he.json index 7c27d407c3..838c1c2ac8 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -157,7 +157,7 @@ "LabelBirthYear": "שנת לידה:", "LabelBlastMessageInterval": "תדירות הודעות דחיפה", "LabelBlastMessageIntervalHelp": "מגדיר את משך הזמן בשניות בין הודעות דחיפה של השרת.", - "LabelCachePath": "נתיב cache:", + "LabelCachePath": "נתיב מטמון:", "LabelChannels": "ערוצים:", "LabelCollection": "אוספים:", "LabelCommunityRating": "דירוג הקהילה:", @@ -204,7 +204,7 @@ "LabelMaxScreenshotsPerItem": "מספר תמונות מסך מקסימאלי לפריט:", "LabelMessageTitle": "כותרת הודעה:", "LabelMetadataDownloadLanguage": "שפת הורדה מועדפת:", - "LabelMetadataPath": "נתיב Metadata:", + "LabelMetadataPath": "נתיב מטא-דאטה:", "LabelMinBackdropDownloadWidth": "רוחב תמונת רקע מינימאלי להורדה:", "LabelMinResumeDuration": "משך המשכה מינימאלי:", "LabelMinResumeDurationHelp": "קובץ קצר מזה לא יהיה ניתן להמשך ניגון מנקודת העצירה", @@ -302,7 +302,7 @@ "OptionAlbumArtist": "אמן אלבום", "OptionAllUsers": "כל המשתמשים", "OptionAllowLinkSharing": "אפשר שיתוף ברשתות חברתיות", - "OptionAllowMediaPlayback": "הרשה נגינת מדיה", + "OptionAllowMediaPlayback": "אפשר ניגון מדיה", "OptionAllowUserToManageServer": "אפשר למשתמש זה לנהל את השרת", "OptionArtist": "אמן", "OptionAscending": "סדר עולה", @@ -419,7 +419,7 @@ "SeriesSettings": "הגדרות סדרה", "SeriesYearToPresent": "{0} - היום", "ServerNameIsRestarting": "שרת Jellyfin - {0} מופעל מחדש.", - "ServerNameIsShuttingDown": "שרת Jellyfin - {0} נכבה.", + "ServerNameIsShuttingDown": "שרת Jellyfin - {0} בתהליך כיבוי.", "ServerUpdateNeeded": "שרת אמבי זה צריך להיות מעודכן. כדי להוריד את הגרסה העדכנית ביותר, בקר בכתובת {0}", "Settings": "הגדרות", "SettingsSaved": "ההגדרות נשמרו.", @@ -801,5 +801,40 @@ "LabelFont": "גופן:", "LabelFolder": "תיקייה:", "LabelFileOrUrl": "קובץ או כתובת אינטרנט:", - "Season": "עונה" + "Season": "עונה", + "OptionEnableAccessFromAllDevices": "אפשר גישה מכל המכשירים", + "Primary": "ראשי", + "Menu": "תפריט", + "LiveTV": "שידורים חיים", + "ManageLibrary": "נהל ספרייה", + "Logo": "לוגו", + "OptionDateAddedImportTime": "השתמש בתאריך הסריקה לתוך הספרייה", + "OptionDateAddedFileTime": "השתמש בתאריך יצירת הקובץ", + "OptionBlockTrailers": "קדימונים", + "OptionBlockMusic": "מוזיקה", + "OptionBlockLiveTvChannels": "ערוצי שידורים חיים", + "OptionBlockBooks": "ספרים", + "OptionAllowRemoteSharedDevices": "אפשר שליטה מרחוק על מכשירים משותפים", + "OptionAllowRemoteControlOthers": "אפשר שליטה מרחוק על משתמשים אחרים", + "SelectAdminUsername": "נא לבחור שם משתמש עבור חשבון המנהל.", + "OptionHideUserFromLoginHelp": "שימושי עבור חשבונות פרטיים או חשבונות מנהל מוסתרים. המשתמש יצטרך להזין את שם המשתמש והסיסמה ידנית על מנת להתחבר.", + "MessagePlayAccessRestricted": "התוכן הזה לא ניתן לניגון כרגע. למידע נוסף, נא ליצור קשר עם מנהל המערכת שלך.", + "MessageContactAdminToResetPassword": "נא ליצור קשר עם מנהל המערכת שלך על מנת לאפס את הסיסמה שלך.", + "HeaderAdmin": "מנהל", + "TabDisplay": "תצוגה", + "HeaderDisplay": "תצוגה", + "Suggestions": "המלצות", + "MessageSyncPlayNoGroupsAvailable": "אין קבוצות זמינות. התחל לנגן משהו קודם.", + "OptionHomeVideos": "תמונות", + "Home": "בית", + "LabelServerName": "שם השרת:", + "TabPlugins": "תוספים", + "MessageNoPluginsInstalled": "אין לך תוספים מותקנים.", + "MessageNoAvailablePlugins": "אין תוספים זמינים.", + "TabLogs": "יומני רישום", + "LabelLogs": "יומני רישום:", + "TabNetworking": "תקשורת", + "TabDVR": "ממיר-מקליט", + "HeaderDVR": "ממיר-מקליט", + "LabelScheduledTaskLastRan": "רץ לאחרונה {0}, במשך {1}." } From cc02cb01cf6df9fedcf381c0b03c2c3f6f275334 Mon Sep 17 00:00:00 2001 From: sharkykh Date: Thu, 6 Aug 2020 12:52:34 +0000 Subject: [PATCH 53/56] Translated using Weblate (Hebrew) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/he/ --- src/strings/he.json | 47 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/src/strings/he.json b/src/strings/he.json index 838c1c2ac8..58eb6ee1b4 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -314,7 +314,7 @@ "OptionContinuing": "ממשיך", "OptionCriticRating": "ציון מבקרים", "OptionCustomUsers": "מותאם אישית", - "OptionDaily": "יומי", + "OptionDaily": "כל יום", "OptionDateAdded": "תאריך הוספה", "OptionDatePlayed": "תאריך ניגון", "OptionDescending": "סדר יורד", @@ -337,7 +337,7 @@ "OptionHasSubtitles": "כתוביות", "OptionHasThemeSong": "שיר נושא", "OptionHasThemeVideo": "סרט נושא", - "OptionHasTrailer": "טריילר", + "OptionHasTrailer": "קדימון", "OptionHideUser": "הסתר משתמש זה בחלון ההתחברות", "OptionImdbRating": "דירוג IMDb", "OptionLikes": "נבחרים", @@ -348,27 +348,27 @@ "OptionOnAppStartup": "בהפעלת התוכנה", "OptionOnInterval": "כל פרק זמן", "OptionParentalRating": "דירוג בקרת הורים", - "OptionPlayCount": "מספר השמעות", + "OptionPlayCount": "כמות ניגונים", "OptionPlayed": "נוגן", - "OptionPremiereDate": "תאריך שידור ראשון", + "OptionPremiereDate": "תאריך בכורה", "OptionProfileAudio": "צליל", "OptionProfilePhoto": "תמונה", "OptionProfileVideo": "וידאו", "OptionProfileVideoAudio": "צליל וידאו", "OptionResumable": "ניתן להמשיך", - "OptionRuntime": "משך", + "OptionRuntime": "זמן ריצה", "OptionSaturday": "שבת", "OptionSpecialEpisode": "ספיישלים", "OptionSunday": "ראשון", "OptionThursday": "חמישי", - "OptionTrackName": "שם השיר", + "OptionTrackName": "שם הרצועה", "OptionTuesday": "שלישי", "OptionTvdbRating": "דירוג TVDB", "OptionUnairedEpisode": "פרקים שלא שודרו", "OptionUnplayed": "לא נוגן", "OptionWakeFromSleep": "הער ממצב שינה", "OptionWednesday": "רביעי", - "OptionWeekly": "שבועי", + "OptionWeekly": "כל שבוע", "OriginalAirDateValue": "תאריך אוויר מקורי: {0}", "Overview": "סקירה כללית", "PackageInstallCancelled": "ההתקנה של {0} (גירסה {1}) בוטלה.", @@ -836,5 +836,36 @@ "TabNetworking": "תקשורת", "TabDVR": "ממיר-מקליט", "HeaderDVR": "ממיר-מקליט", - "LabelScheduledTaskLastRan": "רץ לאחרונה {0}, במשך {1}." + "LabelScheduledTaskLastRan": "רץ לאחרונה {0}, במשך {1}.", + "LabelTheme": "ערכת נושא:", + "LabelTextSize": "גודל טקסט:", + "LabelTextColor": "צבע טקסט:", + "LabelSyncPlayAccessNone": "מבוטל עבור משתמש זה", + "LabelSyncPlayAccessJoinGroups": "אפשר למשתמש להצטרף לקבוצות", + "LabelSyncPlayAccessCreateAndJoinGroups": "אפשר למשתמש ליצור קבוצות ולהצטרף אליהן", + "LabelSyncPlayLeaveGroup": "עזוב קבוצה", + "LabelSyncPlayNewGroupDescription": "צור קבוצה חדשה", + "LabelSyncPlayNewGroup": "קבוצה חדשה", + "MoreFromValue": "עוד מ{0}", + "Writers": "תסריטאים", + "DailyAt": "כל יום ב-{0}", + "OptionWeekends": "סופי שבוע", + "OptionWeekdays": "ימי חול", + "Unplayed": "לא נוגן", + "OptionSubstring": "מחרוזת משנה", + "OptionReleaseDate": "תאריך שחרור", + "OptionRegex": "ביטוי-רגולרי", + "OptionRandom": "אקראי", + "OptionPoster": "פוסטר", + "OptionNone": "כלום", + "OptionMax": "מקסימום", + "List": "רשימה", + "OptionList": "רשימה", + "OptionIsSD": "הבחנה רגילה (SD)", + "OptionIsHD": "הבחנה גבוהה (HD)", + "OptionExternallyDownloaded": "הורדה חיצונית", + "OptionEveryday": "כל יום", + "OptionEnableExternalContentInSuggestions": "הפעל תוכן חיצוני בהמלצות", + "OptionEnableAccessToAllLibraries": "אפשר גישה לכל הספריות", + "OptionEnableAccessToAllChannels": "אפשר גישה לכל הערוצים" } From 88992fd5e73f619834a34003c35be991ed3d1cf8 Mon Sep 17 00:00:00 2001 From: Verkhaliak Anton Date: Thu, 6 Aug 2020 14:19:23 +0000 Subject: [PATCH 54/56] Translated using Weblate (Russian) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/ru/ --- src/strings/ru.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/ru.json b/src/strings/ru.json index 24d5cdd90f..199d0f24ae 100644 --- a/src/strings/ru.json +++ b/src/strings/ru.json @@ -1521,7 +1521,7 @@ "EnableBlurHashHelp": "Рисунки, которые всё ещё загружаются, будут отображаться с размытым заполнением", "EnableBlurHash": "Включить размытые заполнители для изображений", "ButtonSyncPlay": "SyncPlay", - "ButtonCast": "В ролях", + "ButtonCast": "Транслировать", "TabRepositories": "Репозитории", "MessageNoGenresAvailable": "Разрешить поставщикам метаданных получать жанры из интернета.", "MessageAddRepository": "Если вы хотите добавить репозиторий, нажмите кнопку рядом с заголовком и заполните необходимую информацию.", From 7a7e4857658ca35ab61cd6683da159c6ef8c7701 Mon Sep 17 00:00:00 2001 From: Ahmed Mohamed Date: Thu, 6 Aug 2020 15:20:55 +0000 Subject: [PATCH 55/56] Translated using Weblate (Arabic) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/ar/ --- src/strings/ar.json | 118 ++++++++++++++++++++++++++++++-------------- 1 file changed, 82 insertions(+), 36 deletions(-) diff --git a/src/strings/ar.json b/src/strings/ar.json index a9d3d2de41..eb7d6f4249 100644 --- a/src/strings/ar.json +++ b/src/strings/ar.json @@ -99,9 +99,9 @@ "DeleteUserConfirmation": "هل انت متاكد من انك تريد حذف هذا المستخدم ؟", "DeviceAccessHelp": "هذه الميزة تنطبق حصرياً على الأجهزة التي يمكن التعرف عليها فردياً ولن تمنع المتصفح من الدخول عليها. ترشيح الوصول لأجهزة المستخدم ستمنع المستخدمين من استعمال الأجهزة الجديدة إلى أن يتم اعتمادهم من هنا.", "DrmChannelsNotImported": "القنوات المجهزة بإدارة الحقوق الرقمية DRM لن تورّد.", - "EasyPasswordHelp": "الرمز الشخصي الميسرالخاص بك يمكنك من الاتصال إلى خادم مكتبتك، عبر تطبيقات أمبي على الأجهزة أو الدخول على حسابك في الشبكة الداخلية.", + "EasyPasswordHelp": "الرمز pin الميسر الخاص بك يستخدم للوصول بدون اتصل عبر التطبيقات المدعومة أو الدخول على حسابك في الشبكة الداخلية.", "EnablePhotos": "عرض الصور", - "EnablePhotosHelp": "سيتم اكتشاف الصور وعرضها مع ملفات الوسائط الأخرى", + "EnablePhotosHelp": "سيتم اكتشاف الصور وعرضها مع ملفات الوسائط الأخرى.", "ErrorAddingListingsToSchedulesDirect": "كان هناك خطأ في إضافة الاصطفاف لخدمة \"Schedules Direct\" الخاصة بك. خدمة \"Schedules Direct\" لا تسمح إلا بعدد محدود من الاصطفافات لكل حساب. قد تحتاج إلى تسجيل الدخول إلى موقع \"Schedules Direct\" لإزالة الاصطفافات الأخرى من حسابك قبل المتابعة.", "ErrorAddingMediaPathToVirtualFolder": "كان هناك خطأ في إضافة مسار الوسائط. الرجاء التأكد من صحة المسار وأن خادم أمبي لديه صلاحية الوصول إلى الموقع.", "ErrorAddingTunerDevice": "كان هناك خطأ في إضافة جهاز المولف. الرجاء التأكد من صلاحية الوصول إليه ثم عاود المحاولة.", @@ -111,7 +111,7 @@ "ErrorPleaseSelectLineup": "الرجاء اختيار اصطفاف ثم المحاولة مرة أخرى. إن لم تتوفر أية اصطفافات، فالرجاء التأكد من اسم المستخدم وكلمة المرور الخاصة بك، وتأكد من صحة رمزك البريدي.", "ErrorSavingTvProvider": "كان هناك خطأ في حفظ مزود التلفزة. الرجاء التأكد من صلاحية الوصول إليه ثم عاود المحاولة.", "ExitFullscreen": "الخروج من الشاشة الكاملة", - "ExtractChapterImagesHelp": "استخلاص صور الأبواب سيسمح لتطبيقات أمبي أن تظهر لك قوائم تصويرية لتبويبات الأفلام. هذه العملية قد تكون بطيئة، وتستغل قدرة المعالج بشكل ملحوظ، وقد تحتاج إلى حيازة بضعة غيغابايتات من مساحة التخزين بشكل مؤقت. هذه المهمة تعمل خلال عملية استكشاف المقاطع المرئية، كما يمكن أن تحدد لتكون مهمة ليلية مجدولة. يمكنك جدولة العملية من قسم جدولة المهام. لا ينصح بتشغيل هذه المهمة خلال ساعات الذروة من دخول المستخدمين.", + "ExtractChapterImagesHelp": "استخلاص صور الفصول سيسمح للتطبيقات أن تظهر لك قوائم تصويرية لتبويبات الأفلام. هذه العملية قد تكون بطيئة، وتستغل موارد الجهاز بشكل ملحوظ، وقد تحتاج إلى حيازة بضعة غيغابايتات من مساحة التخزين بشكل مؤقت. هذه المهمة تعمل خلال عملية استكشاف المقاطع المرئية، كما يمكن أن تحدد لتكون مهمة ليلية مجدولة. يمكنك جدولة العملية من قسم جدولة المهام. لا ينصح بتشغيل هذه المهمة خلال ساعات الذروة من دخول المستخدمين.", "FFmpegSavePathNotFound": "لم نستطع تحديد موقع ffmpeg باستخدام المسار الذي أدخلته. سوف نحتاج تطبيق FFprobe أيضاً ويجب أن يتواجد في نفس المكان. إن هذه الأجزاء تكون بالعادة محزومة معاً في نفس ملف الإنزال. الرجاء التأكد من المسار المدخل والمحاولة مرة أخرى.", "FastForward": "التقديم السريع", "FileNotFound": "الملف غير موجود.", @@ -129,7 +129,7 @@ "GuideProviderSelectListings": "إختر المبوبات", "H264CrfHelp": "معامل المعدل الثابت CRF هو الجودة الافتراضية لإعدادات مشفر x264. بإمكانك إعطاء قيمة تتراوح بين 0 و 51، وكلما قلت القيمة فسينتج عن ذلك جودة أفضل (على حساب حجم تخزين أعلى). القيم المعقول تتراوح بين 18 و 28. الافتراضي لـ x264 هي 23، لذا فبإمكانك استخدام هذه القيمة كنقطة بداية.", "EncoderPresetHelp": "اختر قيمة أعلى لتحسين السرة والأداء وقيمة أقل لتحسين الجودة.", - "HardwareAccelerationWarning": "تمكين التسريع بعتاد الحاسوب قد يتسبب في عدم استقرار بعض أنواع الأنظمة. تأكد من أن نظام التشغيل الخاص بك محدث إلى آخر نسخة وأن سواقات الفيديو محدثة أيضاً. إذا واجهت أية صعوبات في تسغيل الفيديو بعد تمكين هذه الخاصية، فعليك إرجاع الإعداد إلى وضعية آلي.", + "HardwareAccelerationWarning": "تمكين التسريع بعتاد الحاسوب قد يتسبب في عدم استقرار بعض أنواع الأنظمة. تأكد من أن نظام التشغيل الخاص بك محدث إلى آخر نسخة وأن سواقات الفيديو محدثة أيضاً. إذا واجهت أية صعوبات في تسغيل الفيديو بعد تمكين هذه الخاصية، فعليك إرجاع الإعداد إلى وضعية بلا None.", "HeaderAccessSchedule": "جدول الدخولات", "HeaderAccessScheduleHelp": "إنشئ جدول دخولات لكي تتمكن من تحديد ساعات للدخول.", "HeaderActiveDevices": "الأجهزة المفعّلة", @@ -145,7 +145,7 @@ "HeaderAllowMediaDeletionFrom": "السماح بحذف الوسائط من قبل", "HeaderApiKey": "مفتاح API", "HeaderApiKeys": "مفاتيح API", - "HeaderApiKeysHelp": "التطبيقات الخارجية تحتاج أن تمتلك مفتاح api لكي تتصل بخادم أمبي. هذه المفاتيح تُصدر عن طريق تسجيل الدخول بحساب أمبي، أو عن طريق منح التطبيق مفتاحاً أصدر يدوياً.", + "HeaderApiKeysHelp": "التطبيقات الخارجية تحتاج أن تمتلك مفتاح api لكي تتصل بالخادم. هذه المفاتيح تُصدر عن طريق تسجيل الدخول بمستخدم عادي، أو عن طريق منح التطبيق مفتاحاً أصدر يدوياً.", "HeaderApp": "التطبيق", "HeaderAudioSettings": "إعدادات الصوت", "HeaderBooks": "الكتب", @@ -232,7 +232,7 @@ "HeaderPreferredMetadataLanguage": "اللغة المفضلة لواصفات البيانات", "HeaderProfile": "الحساب", "HeaderProfileInformation": "معلومات العريضة", - "HeaderProfileServerSettingsHelp": "هذه القيم ستتحكم في كيفية تقديم شكل خادم أمبي في الجهاز", + "HeaderProfileServerSettingsHelp": "هذه القيم ستتحكم في كيفية تقديم شكل الخادم في للعملاء.", "HeaderRecentlyPlayed": "تم تشغيله مؤخراً", "HeaderRecordingPostProcessing": "تطبيق ما-بعد-المعالجة للتسجيل", "HeaderRemoteControl": "التحكم عن بعد", @@ -254,7 +254,7 @@ "HeaderSelectServerCachePath": "إختر مسار كاشة الخادم", "HeaderSelectServerCachePathHelp": "تصفح أو أدخل المسار الذي ترغب أن يُستخدم كاشة لملفات الخادم. يجب أن يكون هذا المجلد قابل للكتابة فيه.", "HeaderSelectTranscodingPath": "إختر المسار المؤقت للتشفير البيني", - "HeaderSelectTranscodingPathHelp": "تصفح أو أدخل المسار الذي ترغب أن يُستخدم للملفات المؤقتة للتشفير البيني. يجب أن يكون هذا المجلد قابل للكتابة فيه.", + "HeaderSelectTranscodingPathHelp": "تصفح أو أدخل المسار الذي ترغب أن يُستخدم لملفات التشفير البيني. يجب أن يكون هذا المجلد قابل للكتابة فيه.", "HeaderSendMessage": "أرسل رسالة", "HeaderSeries": "المسلسلات", "HeaderServerSettings": "إعدادات الخادم", @@ -291,17 +291,17 @@ "HeaderXmlSettings": "إعدادات xml", "HeaderYears": "السنوات", "HeadersFolders": "مجلدات", - "ImportFavoriteChannelsHelp": "عند التفعيل، فقط القنوات التي علّمت في المفضلة على هذا المولف ستورد إلى النظام.", - "ImportMissingEpisodesHelp": "عند التمكين، المعلومات الناقصة للحلقات ستورّد إلى قاعدة بيانات أمبي وستعرض داخل المواسم والمسلسلات. قد تتسبب هذه بأوقات أطول بكثير عند تمشيط المكنبات.", + "ImportFavoriteChannelsHelp": "فقط القنوات التي علّمت في المفضلة على جهاز المولف ستورد.", + "ImportMissingEpisodesHelp": "المعلومات الناقصة للحلقات ستورّد إلى قاعدة بياناتك وستعرض داخل المواسم والمسلسلات. قد تتسبب هذه بأوقات أطول بكثير عند تمشيط المكتبات.", "LabelAbortedByServerShutdown": "(تم إهماله بسبب عملية إغلاق الخادم)", "LabelAccessDay": "يوم الأسبوع:", - "LabelAccessEnd": "تاريخ النهاية", - "LabelAccessStart": "تاريخ البداية", + "LabelAccessEnd": "وقت النهاية:", + "LabelAccessStart": "وقت البداية:", "LabelAirDays": "أيام البث:", "LabelAirTime": "وقت البث:", - "LabelAlbum": "الألبوم", + "LabelAlbum": "الألبوم:", "LabelAlbumArtHelp": "PN المستخدمة في رسومات الألبوم، داخل سمة dlna:profileID في upnp:albumArtURI. بعض الأجهزة تحتاج قيمة محددة، مهما كان حجم الصورة.", - "LabelAlbumArtMaxHeight": "الارتفاع الأقصى لرسومات الألبوم", + "LabelAlbumArtMaxHeight": "الارتفاع الأقصى لرسومات الألبوم:", "LabelAlbumArtMaxHeightHelp": "الدقة القصوى لرسومات الألبوم المظهّرة عبر سمة upnp:albumArtURI.", "LabelAlbumArtMaxWidth": "العرض الأقصى لرسوم الألبوم:", "LabelAlbumArtMaxWidthHelp": "الدقة القصوى لرسومات الألبوم المظهّرة عبر سمة upnp:albumArtURI.", @@ -310,42 +310,42 @@ "LabelAll": "الجميع", "LabelAllowHWTranscoding": "السماح بالتشفير البيني بعتاد الحاسب", "LabelAppName": "اسم التطبيق", - "LabelAppNameExample": "مثال: Sickbeard، NzbDrone", + "LabelAppNameExample": "مثال: Sickbeard، Sonarr", "LabelArtists": "الفنانون:", - "LabelArtistsHelp": "فصل الاستعمالات المتعددة ;", + "LabelArtistsHelp": "افصل بين الفنانين ب ; فاصلة منقوطة.", "LabelAudioLanguagePreference": "اللغة المفضلة للصوت:", "LabelBindToLocalNetworkAddress": "إربطه إلى عنوان شبكة محلي:", - "LabelBindToLocalNetworkAddressHelp": "هذا خياري. امتطي عنوان الآي بي المحلي لربطه بخادم http. إذا ترك فارغاً، فإن الخادم سيربطه بجميع العناوين المتاحة. تغيير هذه القيمة يتطلب إعادة تشغيل خادم أمبي.", - "LabelBlastMessageInterval": "فترات بث رسالة قيد التشغيل (بالثواني)", - "LabelBlastMessageIntervalHelp": "يحدد الفترة بالثواني بين يث رسائل قيد التشغيل", - "LabelCache": "ذاكرة الكاشة", - "LabelCachePath": "مسار ذاكرة الكاشة:", - "LabelCachePathHelp": "حدد موقع مخصص لملفات كاشة الخادم، مثل الصور وغيرها. أترك هذه الخانة فارغة لاستعمال القيمة التلقائية.", + "LabelBindToLocalNetworkAddressHelp": "تجاوز عنوان الآي بي المحلي لربطه بخادم http. إذا ترك فارغاً، فإن الخادم سيربطه بجميع العناوين المتاحة. تغيير هذه القيمة يتطلب إعادة تشغيل خادم جيلليفن.", + "LabelBlastMessageInterval": "فترات بث رسالة قيد التشغيل", + "LabelBlastMessageIntervalHelp": "يحدد الفترة بالثواني بين بث رسائل قيد التشغيل.", + "LabelCache": "مَخبأ (كاش):", + "LabelCachePath": "مسار ذاكرة الكاش:", + "LabelCachePathHelp": "حدد موقع مخصص لملفات الخادم المؤقتة، مثل الصور وغيرها. أترك هذه الخانة فارغة لاستعمال القيمة الافتراضية.", "LabelCancelled": "تم الإلغاء", - "LabelCollection": "المجموعة", + "LabelCollection": "المجموعة:", "LabelCommunityRating": "تقييم المجتمع:", - "LabelContentType": "نوع المحتوى", + "LabelContentType": "نوع المحتوى:", "LabelCountry": "البلد:", "LabelCurrentPassword": "كلمة السر الحالية:", - "LabelCustomCertificatePath": "مسار شهادة ssl مخصص:", + "LabelCustomCertificatePath": "مسار شهادة SSL المخصص:", "LabelCustomCertificatePathHelp": "مسار ملف PKCS # 12 يحتوي على شهادة ومفتاح خاص لتمكين دعم TLS على مجال مخصص.", - "LabelCustomCss": "تنيسق CSS مخصوص:", - "LabelCustomCssHelp": "طبق تنسيق css مخصوصة لواجهة الويب.", + "LabelCustomCss": "تنيسق CSS مخصص:", + "LabelCustomCssHelp": "طبق تنسيقك css المخصص لواجهة الويب.", "LabelCustomDeviceDisplayName": "اسم العرض:", - "LabelCustomDeviceDisplayNameHelp": "أذكر اسم عرض مخصوص أو أتركه فارغاً لاستخدام", + "LabelCustomDeviceDisplayNameHelp": "أذكر اسم عرض مخصوص أو أتركه فارغاً لاستخدام الاسم المبلغ من الجهاز.", "LabelDateAddedBehavior": "كيف يتصرف المحتوى الجديد نحو \"تاريخ الإضافة\" الخاص به:", - "LabelDateAddedBehaviorHelp": "إذا استعرضت قيمة واصفات البيانا فإنها سوف تستخدم قبل أن تستخدم أي من هذه الخيارات.", + "LabelDateAddedBehaviorHelp": "إذا اخذت واصفات البيانات قيمة، فإنها سوف تستخدم قبل أن تستخدم أي من هذه الخيارات.", "LabelDay": "اليوم:", "LabelDeathDate": "تاريخ الوفاة:", - "LabelDefaultUser": "المستخدم الافتراضي", + "LabelDefaultUser": "المستخدم الافتراضي:", "LabelDefaultUserHelp": "لتحديد مكتبة المستخدم التي تظهر على الأجهزة المتصلة. بإمكان الامتطاء على هذه القيمة لكل جهاز عن طريق عرائض الأجهزة.", "LabelDeviceDescription": "وصف الجهاز", - "LabelDidlMode": "طور didl:", + "LabelDidlMode": "طور DIDL:", "LabelDisplayMissingEpisodesWithinSeasons": "أظهر الحلقات المفقودة في مجلدات المواسم", "LabelDisplayName": "الاسم المعروض:", "LabelDisplaySpecialsWithinSeasons": "أظهر الحلقات الخاصة في المواسم التي بثت فيها", "LabelDownMixAudioScale": "تعزيز الصوت عند تقليل توزيع قنوات الصوت:", - "LabelDownMixAudioScaleHelp": "تعزيز الصوت عند تقليل توزيع قنوات الصوت. حدد القيمة بـ 1 للمحافظة على القيمة الأصلية للصوت.", + "LabelDownMixAudioScaleHelp": "تعزيز الصوت عند تقليل توزيع قنوات الصوت. حدد القيمة ب 1 للمحافظة على القيمة الأصلية للصوت.", "LabelDownloadLanguages": "إنزال اللغة:", "LabelDynamicExternalId": "معرفة {0}:", "LabelEasyPinCode": "الرمز الشخصي الميسر:", @@ -354,8 +354,8 @@ "LabelEnableAutomaticPortMap": "فعل الخاصية الآلية في التوفيق بين المنافذ", "LabelEnableAutomaticPortMapHelp": "حاول التوفيق بين المنفذ العالمي والمنفذ المحلي آلياً باستخدام آلية UPnP. هذه الخاصية قد لا تعمل مع بعض أنواع الراوترات.", "LabelEnableBlastAliveMessages": "بث رسائل قيد التشغيل", - "LabelEnableBlastAliveMessagesHelp": "فعل هذه الخاصية إذا كان الخادم لا يكتشف بكفاءة من قبل أجهزة UPnP الأخرى على شبكتك", - "LabelEnableDlnaClientDiscoveryInterval": "فترات استكشاف العملاء (بالثواني)", + "LabelEnableBlastAliveMessagesHelp": "فعل هذه الخاصية إذا كان الخادم لا يكتشف بكفاءة من قبل أجهزة UPnP الأخرى على شبكتك.", + "LabelEnableDlnaClientDiscoveryInterval": "فترات استكشاف العملاء", "LabelEnableDlnaClientDiscoveryIntervalHelp": "يحدد الفترة بالثواني بين عمليات بحث SSDP التي يقوم بها أمبي.", "LabelEnableDlnaDebugLogging": "تفعيل خاصية كشوفات أخطاء DLNA", "LabelEnableDlnaDebugLoggingHelp": "هذه ستنشئ سجلات كشفية ضخمة ولا ينبغي تفعيلها إلا عند الحاجة إليها بغرض استكشاف الأخطاء وحصرها.", @@ -930,7 +930,7 @@ "Backdrops": "خلفيات متغيرة للصفحة", "Backdrop": "خلفية متغيرة للصفحة", "Auto": "تلقائي", - "AuthProviderHelp": "حدد مقدم المصادقات ليتم استخدامه لمصادقة كلمة مرور هذا المستخدم.", + "AuthProviderHelp": "اختار مقدم المصادقة ليتم استخدامه لمصادقة كلمة مرور هذا المستخدم.", "AroundTime": "حول", "AttributeNew": "جديد", "AspectRatio": "نسبة العرض الى الارتفاع", @@ -1038,7 +1038,7 @@ "Director": "المخرج", "DirectPlaying": "بث بدون تحويل الصيغة", "DirectStreaming": "البث المباشر", - "DirectStreamHelp2": "البث المباشر للملف يستخدم طاقة معالجة قليلة جدًا دون أي خسارة في جودة الفيديو.", + "DirectStreamHelp2": "البث المباشر للملف يستخدم قوة معالجة قليلة جدًا دون أي خسارة في جودة الفيديو.", "DirectStreamHelp1": "الوسائط متوافقة مع الجهاز فيما يتعلق بالدقة ونوع الوسائط (H.264 ، AC3 ، إلخ) ، ولكنها في حاوية ملفات غير متوافقة (mkv ، avi ، wmv ، إلخ). سيتم إعادة حزم الفيديو في الوقت الحقيقي قبل بثه إلى الجهاز.", "DetectingDevices": "يتم الكشف عن الأجهزة", "Desktop": "سطح المكتب", @@ -1139,5 +1139,51 @@ "Dislike": "لم يعجبنى", "ButtonSyncPlay": "SyncPlay", "ExtraLarge": "كبير جدا", - "EnableNextVideoInfoOverlayHelp": "في نهاية الفيديو, عرض معلومات عن الفيديو القادم في قائمة التشغيل." + "EnableNextVideoInfoOverlayHelp": "في نهاية الفيديو, عرض معلومات عن الفيديو القادم في قائمة التشغيل.", + "LabelDroppedFrames": "الاطارات الساقطة:", + "LabelDropImageHere": "اسقط صورة هنا، او ضغط تصفح.", + "LabelDisplayOrder": "ترتيب المعروض:", + "LabelDisplayMode": "وضع المعروض:", + "LabelDisplayLanguageHelp": "ترجمة جيلليفين هو مشروع مستمر.", + "LabelDisplayLanguage": "لغة العرض:", + "LabelDiscNumber": "رقم القرص:", + "LabelDeinterlaceMethod": "طريقة تقليل التشابك:", + "LabelDefaultScreen": "الشاشة الافتراضية:", + "LabelDateTimeLocale": "وقت و تاريخ محلي:", + "LabelDateAdded": "تاريخ الاضافة:", + "LabelCustomRating": "تقييم مخصص:", + "LabelCriticRating": "تقييم النقاد:", + "LabelCorruptedFrames": "الإطارات التالفة:", + "LabelChannels": "القنوات:", + "LabelCertificatePasswordHelp": "اذا تطلبت شهادتك الامنية كلمة مرور، من فضلك ادخلها هنا.", + "LabelCertificatePassword": "كلمة مرور الشهادة الامنية:", + "LabelBurnSubtitles": "الترجمات المحروقة:", + "LabelBlockContentWithTags": "احجب العناصر بالعلامات:", + "LabelBitrate": "معدل البت:", + "LabelBirthYear": "عام الميلاد:", + "LabelBirthDate": "تاريخ الميلاد:", + "LabelAutomaticallyRefreshInternetMetadataEvery": "حدث وصف البيانات تلقائيا من الانترنت:", + "LabelAuthProvider": "مقدم التصديق:", + "LabelAudioSampleRate": "سرعة معينة الصوت:", + "LabelAudioCodec": "ترميز الصوت:", + "LabelAudioChannels": "قنوات الصوت:", + "LabelAudioBitrate": "معدل بث الصوت:", + "LabelAudioBitDepth": "عمق بث الصوت:", + "LabelAudio": "الصوت", + "LabelAllowedRemoteAddressesMode": "وضع مرشح عنوان المضيف IP البعيد:", + "LabelAllowedRemoteAddresses": "مرشح عنوان المضيف IP البعيد:", + "LabelAirsBeforeSeason": "عروض بث قبل الموسم:", + "LabelAirsBeforeEpisode": "عروض بث قبل الحلقة:", + "LabelAirsAfterSeason": "عروض بث بعد الموسم:", + "Label3DFormat": "صيغة ثلاثية الابعاد:", + "Kids": "اطفال", + "Items": "عناصر", + "ItemCount": "{0} عنصر", + "InstantMix": "خلط فوري", + "HeaderSyncPlayEnabled": "تزامن اللعب ممكَّن", + "HeaderSyncPlaySelectGroup": "انضم لمجموعة", + "EnableDetailsBannerHelp": "اظهر صوره اللافته اعلى عنصر تفاصيل الصفحة.", + "EnableDetailsBanner": "لافتة التفاصيل", + "EnableDecodingColorDepth10Vp9": "تمكين ترميز ال10 بت عبر العتاد الصلب من اجل VP9", + "EnableDecodingColorDepth10Hevc": "تمكين ترميز ال10 بت عبر العتاد الصلب من اجل HEVC" } From 637c134145a7b5ec3e405dc9a2cd157edd1c66ce Mon Sep 17 00:00:00 2001 From: sharkykh Date: Thu, 6 Aug 2020 15:47:14 +0000 Subject: [PATCH 56/56] Translated using Weblate (Hebrew) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/he/ --- src/strings/he.json | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/strings/he.json b/src/strings/he.json index 58eb6ee1b4..c266f587c2 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -471,7 +471,7 @@ "TabTrailers": "טריילרים", "TabTranscoding": "קידוד", "TabUpcoming": "בקרוב", - "Tags": "תגים", + "Tags": "מילות מפתח", "TellUsAboutYourself": "ספר לנו על עצמך", "ThisWizardWillGuideYou": "אשף זה יעזור לך בהתליך ההתקנה.", "Thursday": "חמישי", @@ -588,7 +588,7 @@ "MessageConfirmRestart": "‫האם אתה בטוח שברצונך לאתחל את שרת ה-Jellyfin‏?", "HeaderThisUserIsCurrentlyDisabled": "משתמש זה אינו פעיל כרגע", "HeaderTaskTriggers": "טריגרים של המשימה", - "HeaderTags": "תגיות", + "HeaderTags": "מילות מפתח", "HeaderStopRecording": "עצור הקלטה", "HeaderSortOrder": "סדר מיון", "HeaderSortBy": "מיין לפי", @@ -867,5 +867,7 @@ "OptionEveryday": "כל יום", "OptionEnableExternalContentInSuggestions": "הפעל תוכן חיצוני בהמלצות", "OptionEnableAccessToAllLibraries": "אפשר גישה לכל הספריות", - "OptionEnableAccessToAllChannels": "אפשר גישה לכל הערוצים" + "OptionEnableAccessToAllChannels": "אפשר גישה לכל הערוצים", + "HeaderSyncPlaySelectGroup": "הצטרף לקבוצה", + "TabUsers": "משתמשים" }