From 6cfcf36c3cdc1663179806810bb10826ba634657 Mon Sep 17 00:00:00 2001 From: MrK Date: Sun, 17 Sep 2023 23:27:44 +0100 Subject: [PATCH 01/74] Fixing bug #5584 by sending the proper Sort params to the API --- src/components/playback/playbackmanager.js | 16 ++++++++++++++-- src/components/shortcuts.js | 18 ++++++++++++++++-- src/controllers/list.js | 4 +++- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 05117fd08..c1ba16333 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -1806,12 +1806,18 @@ class PlaybackManager { MediaTypes: 'Audio' }); } else if (firstItem.MediaType === 'Photo') { + const sortOptions = options.sortOptions || {}; + let sortByValue = options.shuffle ? 'Random' : sortOptions.sortBy; + if (sortByValue == null) { + sortByValue = 'SortName'; + } promise = getItemsForPlayback(serverId, { ParentId: firstItem.ParentId, Filters: 'IsNotFolder', // Setting this to true may cause some incorrect sorting Recursive: false, - SortBy: options.shuffle ? 'Random' : 'SortName', + SortBy: sortByValue, + SortOrder: sortOptions.sortOrder, MediaTypes: 'Photo,Video', Limit: UNLIMITED_ITEMS }).then(function (result) { @@ -1849,11 +1855,17 @@ class PlaybackManager { MediaTypes: 'Audio' }); } else if (firstItem.IsFolder && firstItem.CollectionType === 'homevideos') { + const sortOptions = options.sortOptions || {}; + let sortByValue = options.shuffle ? 'Random' : sortOptions.sortBy; + if (sortByValue == null) { + sortByValue = 'SortName'; + } promise = getItemsForPlayback(serverId, mergePlaybackQueries({ ParentId: firstItem.Id, Filters: 'IsNotFolder', Recursive: true, - SortBy: options.shuffle ? 'Random' : 'SortName', + SortBy: sortByValue, + SortOrder: sortOptions.sortOrder, // Only include Photos because we do not handle mixed queues currently MediaTypes: 'Photo', Limit: UNLIMITED_ITEMS diff --git a/src/components/shortcuts.js b/src/components/shortcuts.js index 7dc840e8b..10174d886 100644 --- a/src/components/shortcuts.js +++ b/src/components/shortcuts.js @@ -11,6 +11,7 @@ import dom from '../scripts/dom'; import recordingHelper from './recordingcreator/recordinghelper'; import ServerConnections from './ServerConnections'; import toast from './toast/toast'; +import * as userSettings from '../scripts/settings/userSettings'; function playAllFromHere(card, serverId, queue) { const parent = card.parentNode; @@ -165,6 +166,14 @@ function showPlayMenu(card, target) { }); } +function getSortValues(parentId) { + const basekey = 'items-' + parentId + '-Folder'; + return { + sortBy: userSettings.getFilter(basekey + '-sortby'), + sortOrder: userSettings.getFilter(basekey + '-sortorder') === 'Descending' ? 'Descending' : 'Ascending' + }; +} + function executeAction(card, target, action) { target = target || card; @@ -175,6 +184,10 @@ function executeAction(card, target, action) { id = card.getAttribute('data-id'); } + const itemsContainer = dom.parentWithClass(card, 'itemsContainer'); + + const parentId = itemsContainer.getAttribute('data-parentid'); + const item = getItemInfoFromCard(card); const serverId = item.ServerId; @@ -200,12 +213,13 @@ function executeAction(card, target, action) { }); } else if (action === 'play' || action === 'resume') { const startPositionTicks = parseInt(card.getAttribute('data-positionticks') || '0', 10); - + if (playbackManager.canPlay(item)) { playbackManager.play({ ids: [playableItemId], startPositionTicks: startPositionTicks, - serverId: serverId + serverId: serverId, + sortOptions: getSortValues(parentId) }); } else { console.warn('Unable to play item', item); diff --git a/src/controllers/list.js b/src/controllers/list.js index 0378a1025..fc2366a3e 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -722,11 +722,13 @@ class ItemsView { function play() { const currentItem = self.currentItem; + const values = self.getSortValues(); if (currentItem && !self.hasFilters) { playbackManager.play({ items: [currentItem], - autoplay: true + autoplay: true, + sortOptions: values }); } else { getItems(self, self.params, currentItem, null, 0, 300).then(function (result) { From 344a6bfad6b7b88749f93cc236dc7bd2b7c4065f Mon Sep 17 00:00:00 2001 From: MrK Date: Sun, 17 Sep 2023 23:33:58 +0100 Subject: [PATCH 02/74] Updated CONTRIBUTORS.md --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index eccfd4cf2..835b7db64 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -132,3 +132,4 @@ - [jomp16](https://github.com/jomp16) - [Leon de Klerk](https://github.com/leondeklerk) - [CrispyBaguette](https://github.com/CrispyBaguette) + - [v0idMrK](https://github.com/v0idMrK) From ecba6dccb95e5859c0eb934d2df3ff49da909dca Mon Sep 17 00:00:00 2001 From: MrK Date: Mon, 18 Sep 2023 13:00:22 +0100 Subject: [PATCH 03/74] Removing bad trailing space --- src/components/shortcuts.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/shortcuts.js b/src/components/shortcuts.js index 10174d886..22366c5c7 100644 --- a/src/components/shortcuts.js +++ b/src/components/shortcuts.js @@ -213,7 +213,6 @@ function executeAction(card, target, action) { }); } else if (action === 'play' || action === 'resume') { const startPositionTicks = parseInt(card.getAttribute('data-positionticks') || '0', 10); - if (playbackManager.canPlay(item)) { playbackManager.play({ ids: [playableItemId], From f922742d862e0111e785efd0fb8002098be8de0a Mon Sep 17 00:00:00 2001 From: MrK Date: Mon, 18 Sep 2023 19:36:21 +0100 Subject: [PATCH 04/74] Contributors file updated correctly Adds shortcuts.js function to get sort order Added sort order technique to most types of media on playbackmanager.js --- CONTRIBUTORS.md | 2 +- src/components/playback/playbackmanager.js | 42 +++++++++++++--------- src/components/shortcuts.js | 1 + 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 835b7db64..3cb25b462 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -66,6 +66,7 @@ - [Fishbigger](https://github.com/fishbigger) - [sleepycatcoding](https://github.com/sleepycatcoding) - [TheMelmacian](https://github.com/TheMelmacian) + - [v0idMrK](https://github.com/v0idMrK) # Emby Contributors @@ -132,4 +133,3 @@ - [jomp16](https://github.com/jomp16) - [Leon de Klerk](https://github.com/leondeklerk) - [CrispyBaguette](https://github.com/CrispyBaguette) - - [v0idMrK](https://github.com/v0idMrK) diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index c1ba16333..60173e8ed 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -1773,6 +1773,18 @@ class PlaybackManager { }); } + function getSortOptions(options) { + const sortOptions = options.sortOptions || {}; + let sortByValue = options.shuffle ? 'Random' : sortOptions.sortBy; + if (sortByValue == null) { + sortByValue = 'SortName'; + } + return { + sortBy: sortByValue, + sortOrder: sortOptions.sortOrder + }; + } + function translateItemsForPlayback(items, options) { if (items.length > 1 && options && options.ids) { // Use the original request id array for sorting the result in the proper order @@ -1788,6 +1800,8 @@ class PlaybackManager { const queryOptions = options.queryOptions || {}; + const sortOptions = getSortOptions(options); + if (firstItem.Type === 'Program') { promise = getItemsForPlayback(serverId, { Ids: firstItem.ChannelId @@ -1802,21 +1816,17 @@ class PlaybackManager { ArtistIds: firstItem.Id, Filters: 'IsNotFolder', Recursive: true, - SortBy: options.shuffle ? 'Random' : 'SortName', + SortBy: sortOptions.sortBy, + SortOrder: sortOptions.sortOrder, MediaTypes: 'Audio' }); } else if (firstItem.MediaType === 'Photo') { - const sortOptions = options.sortOptions || {}; - let sortByValue = options.shuffle ? 'Random' : sortOptions.sortBy; - if (sortByValue == null) { - sortByValue = 'SortName'; - } promise = getItemsForPlayback(serverId, { ParentId: firstItem.ParentId, Filters: 'IsNotFolder', // Setting this to true may cause some incorrect sorting Recursive: false, - SortBy: sortByValue, + SortBy: sortOptions.sortBy, SortOrder: sortOptions.sortOrder, MediaTypes: 'Photo,Video', Limit: UNLIMITED_ITEMS @@ -1841,7 +1851,8 @@ class PlaybackManager { Filters: 'IsNotFolder', // Setting this to true may cause some incorrect sorting Recursive: false, - SortBy: options.shuffle ? 'Random' : 'SortName', + SortBy: sortOptions.sortBy, + SortOrder: sortOptions.sortOrder, // Only include Photos because we do not handle mixed queues currently MediaTypes: 'Photo', Limit: UNLIMITED_ITEMS @@ -1851,20 +1862,16 @@ class PlaybackManager { GenreIds: firstItem.Id, Filters: 'IsNotFolder', Recursive: true, - SortBy: options.shuffle ? 'Random' : 'SortName', + SortBy: sortOptions.sortBy, + SortOrder: sortOptions.sortOrder, MediaTypes: 'Audio' }); } else if (firstItem.IsFolder && firstItem.CollectionType === 'homevideos') { - const sortOptions = options.sortOptions || {}; - let sortByValue = options.shuffle ? 'Random' : sortOptions.sortBy; - if (sortByValue == null) { - sortByValue = 'SortName'; - } promise = getItemsForPlayback(serverId, mergePlaybackQueries({ ParentId: firstItem.Id, Filters: 'IsNotFolder', Recursive: true, - SortBy: sortByValue, + SortBy: sortOptions.sortBy, SortOrder: sortOptions.sortOrder, // Only include Photos because we do not handle mixed queues currently MediaTypes: 'Photo', @@ -1872,10 +1879,12 @@ class PlaybackManager { }, queryOptions)); } else if (firstItem.IsFolder) { let sortBy = null; + let sortOrder = null; if (options.shuffle) { sortBy = 'Random'; } else if (firstItem.Type !== 'BoxSet') { - sortBy = 'SortName'; + sortBy = sortOptions.sortBy; + sortOrder = sortOptions.sortOrder; } promise = getItemsForPlayback(serverId, mergePlaybackQueries({ ParentId: firstItem.Id, @@ -1883,6 +1892,7 @@ class PlaybackManager { Recursive: true, // These are pre-sorted SortBy: sortBy, + SortOrder: sortOrder, MediaTypes: 'Audio,Video' }, queryOptions)); } else if (firstItem.Type === 'Episode' && items.length === 1 && getPlayer(firstItem, options).supportsProgress !== false) { diff --git a/src/components/shortcuts.js b/src/components/shortcuts.js index 22366c5c7..d4de04dbf 100644 --- a/src/components/shortcuts.js +++ b/src/components/shortcuts.js @@ -213,6 +213,7 @@ function executeAction(card, target, action) { }); } else if (action === 'play' || action === 'resume') { const startPositionTicks = parseInt(card.getAttribute('data-positionticks') || '0', 10); + if (playbackManager.canPlay(item)) { playbackManager.play({ ids: [playableItemId], From 580ad5f1a8dfde72be012c062b3405c766eb8ca9 Mon Sep 17 00:00:00 2001 From: MrK Date: Tue, 19 Sep 2023 22:29:54 +0100 Subject: [PATCH 05/74] Added getSortOptions to userSettings.js and cleaned up the shortcuts.js and list.js to use the above method --- src/components/shortcuts.js | 16 ++++------------ src/controllers/list.js | 5 +---- src/scripts/settings/userSettings.js | 13 +++++++++++++ 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/components/shortcuts.js b/src/components/shortcuts.js index d4de04dbf..70bf264fc 100644 --- a/src/components/shortcuts.js +++ b/src/components/shortcuts.js @@ -166,14 +166,6 @@ function showPlayMenu(card, target) { }); } -function getSortValues(parentId) { - const basekey = 'items-' + parentId + '-Folder'; - return { - sortBy: userSettings.getFilter(basekey + '-sortby'), - sortOrder: userSettings.getFilter(basekey + '-sortorder') === 'Descending' ? 'Descending' : 'Ascending' - }; -} - function executeAction(card, target, action) { target = target || card; @@ -184,11 +176,11 @@ function executeAction(card, target, action) { id = card.getAttribute('data-id'); } + const item = getItemInfoFromCard(card); + const itemsContainer = dom.parentWithClass(card, 'itemsContainer'); - const parentId = itemsContainer.getAttribute('data-parentid'); - - const item = getItemInfoFromCard(card); + const sortParentId = 'items-' + (item.IsFolder ? item.Id : itemsContainer.getAttribute('data-parentid')) + '-Folder'; const serverId = item.ServerId; const type = item.Type; @@ -219,7 +211,7 @@ function executeAction(card, target, action) { ids: [playableItemId], startPositionTicks: startPositionTicks, serverId: serverId, - sortOptions: getSortValues(parentId) + sortOptions: userSettings.getSortValues(sortParentId) }); } else { console.warn('Unable to play item', item); diff --git a/src/controllers/list.js b/src/controllers/list.js index fc2366a3e..ded9d921e 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -962,10 +962,7 @@ class ItemsView { getSortValues() { const basekey = this.getSettingsKey(); - return { - sortBy: userSettings.getFilter(basekey + '-sortby') || this.getDefaultSortBy(), - sortOrder: userSettings.getFilter(basekey + '-sortorder') === 'Descending' ? 'Descending' : 'Ascending' - }; + return userSettings.getSortValues(basekey); } getDefaultSortBy() { diff --git a/src/scripts/settings/userSettings.js b/src/scripts/settings/userSettings.js index 691b07cb4..26fc2100e 100644 --- a/src/scripts/settings/userSettings.js +++ b/src/scripts/settings/userSettings.js @@ -622,6 +622,18 @@ export class UserSettings { getFilter(key) { return this.get(key, true); } + + /** + * Gets the current sort values + * @param {string} key - Filter key. + * @return {Object} sortOptions object + */ + getSortValues(key) { + return { + sortBy: this.getFilter(key + '-sortby'), + sortOrder: this.getFilter(key + '-sortorder') === 'Descending' ? 'Descending' : 'Ascending' + }; + } } export const currentSettings = new UserSettings; @@ -672,3 +684,4 @@ export const customCss = currentSettings.customCss.bind(currentSettings); export const disableCustomCss = currentSettings.disableCustomCss.bind(currentSettings); export const getSavedView = currentSettings.getSavedView.bind(currentSettings); export const saveViewSetting = currentSettings.saveViewSetting.bind(currentSettings); +export const getSortValues = currentSettings.getSortValues.bind(currentSettings); From ee791f9d0d2b7c0bc96e6109415c1032d92f2a24 Mon Sep 17 00:00:00 2001 From: MrK Date: Wed, 20 Sep 2023 17:44:55 +0100 Subject: [PATCH 06/74] Changed from using sortOptions to using already implemented queryOptions Null verification for parentid on shortcuts.js itemContextMenu is now obeying to sorting --- src/components/itemContextMenu.js | 30 +++++++++++- src/components/playback/playbackmanager.js | 55 +++++++--------------- src/components/shortcuts.js | 4 +- src/controllers/list.js | 4 +- src/scripts/settings/userSettings.js | 24 ++++++++-- 5 files changed, 70 insertions(+), 47 deletions(-) diff --git a/src/components/itemContextMenu.js b/src/components/itemContextMenu.js index 0ec982f15..fe01437b9 100644 --- a/src/components/itemContextMenu.js +++ b/src/components/itemContextMenu.js @@ -9,6 +9,8 @@ import itemHelper from './itemHelper'; import { playbackManager } from './playback/playbackmanager'; import ServerConnections from './ServerConnections'; import toast from './toast/toast'; +import * as userSettings from '../scripts/settings/userSettings'; +import libraryMenu from '../scripts/libraryMenu'; export function getCommands(options) { const item = options.item; @@ -567,6 +569,29 @@ function deleteSeriesTimer(apiClient, item, resolve, command) { }); } +function getSettingsKey(item) { + if (item.IsFolder) { + return 'Folder'; + } + const itemType = item.MediaType; + switch (itemType) { + case 'Movie': + case 'BoxSet': + case 'Video': + return 'movies'; + case 'Audio': + return 'songs'; + case 'MusicAlbum': + return 'musicalbums'; + case 'MusicArtist': + return 'musicartists'; + case 'MusicGenre': + return 'genres'; + case 'MusicPlaylist': + return 'musicplaylists'; + } +} + function play(item, resume, queue, queueNext) { let method = 'play'; if (queue) { @@ -589,9 +614,12 @@ function play(item, resume, queue, queueNext) { serverId: item.ServerId }); } else { + const sortParentId = item.IsFolder ? ('items-' + item.Id) : libraryMenu.getTopParentId() + '-' + getSettingsKey(item); + const sortValues = userSettings.getSortValues(sortParentId); playbackManager[method]({ items: [item], - startPositionTicks: startPosition + startPositionTicks: startPosition, + queryOptions: sortValues }); } } diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 60173e8ed..1981fdc57 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -145,7 +145,10 @@ function createStreamInfoFromUrlItem(item) { } function mergePlaybackQueries(obj1, obj2) { - const query = Object.assign(obj1, obj2); + const query = obj1; + for (const key in obj2) { + if (obj2[key] !== undefined) query[key] = obj2[key]; + } const filters = query.Filters ? query.Filters.split(',') : []; if (filters.indexOf('IsNotFolder') === -1) { @@ -1773,18 +1776,6 @@ class PlaybackManager { }); } - function getSortOptions(options) { - const sortOptions = options.sortOptions || {}; - let sortByValue = options.shuffle ? 'Random' : sortOptions.sortBy; - if (sortByValue == null) { - sortByValue = 'SortName'; - } - return { - sortBy: sortByValue, - sortOrder: sortOptions.sortOrder - }; - } - function translateItemsForPlayback(items, options) { if (items.length > 1 && options && options.ids) { // Use the original request id array for sorting the result in the proper order @@ -1800,8 +1791,6 @@ class PlaybackManager { const queryOptions = options.queryOptions || {}; - const sortOptions = getSortOptions(options); - if (firstItem.Type === 'Program') { promise = getItemsForPlayback(serverId, { Ids: firstItem.ChannelId @@ -1812,25 +1801,23 @@ class PlaybackManager { SortBy: options.shuffle ? 'Random' : null }); } else if (firstItem.Type === 'MusicArtist') { - promise = getItemsForPlayback(serverId, { + promise = getItemsForPlayback(serverId, mergePlaybackQueries({ ArtistIds: firstItem.Id, Filters: 'IsNotFolder', Recursive: true, - SortBy: sortOptions.sortBy, - SortOrder: sortOptions.sortOrder, + SortBy: options.shuffle ? 'Random' : 'SortName', MediaTypes: 'Audio' - }); + }, queryOptions)); } else if (firstItem.MediaType === 'Photo') { - promise = getItemsForPlayback(serverId, { + promise = getItemsForPlayback(serverId, mergePlaybackQueries({ ParentId: firstItem.ParentId, Filters: 'IsNotFolder', // Setting this to true may cause some incorrect sorting Recursive: false, - SortBy: sortOptions.sortBy, - SortOrder: sortOptions.sortOrder, MediaTypes: 'Photo,Video', + sortBy: options.shuffle ? 'Random' : 'SortName', Limit: UNLIMITED_ITEMS - }).then(function (result) { + }, queryOptions)).then(function (result) { const playbackItems = result.Items; let index = playbackItems.map(function (i) { @@ -1846,45 +1833,40 @@ class PlaybackManager { return Promise.resolve(result); }); } else if (firstItem.Type === 'PhotoAlbum') { - promise = getItemsForPlayback(serverId, { + promise = getItemsForPlayback(serverId, mergePlaybackQueries({ ParentId: firstItem.Id, Filters: 'IsNotFolder', // Setting this to true may cause some incorrect sorting Recursive: false, - SortBy: sortOptions.sortBy, - SortOrder: sortOptions.sortOrder, + SortBy: options.shuffle ? 'Random' : 'SortName', // Only include Photos because we do not handle mixed queues currently MediaTypes: 'Photo', Limit: UNLIMITED_ITEMS - }); + }, queryOptions)); } else if (firstItem.Type === 'MusicGenre') { - promise = getItemsForPlayback(serverId, { + promise = getItemsForPlayback(serverId, mergePlaybackQueries({ GenreIds: firstItem.Id, Filters: 'IsNotFolder', Recursive: true, - SortBy: sortOptions.sortBy, - SortOrder: sortOptions.sortOrder, + SortBy: options.shuffle ? 'Random' : 'SortName', MediaTypes: 'Audio' - }); + })); } else if (firstItem.IsFolder && firstItem.CollectionType === 'homevideos') { promise = getItemsForPlayback(serverId, mergePlaybackQueries({ ParentId: firstItem.Id, Filters: 'IsNotFolder', Recursive: true, - SortBy: sortOptions.sortBy, - SortOrder: sortOptions.sortOrder, + SortBy: options.shuffle ? 'Random' : 'SortName', // Only include Photos because we do not handle mixed queues currently MediaTypes: 'Photo', Limit: UNLIMITED_ITEMS }, queryOptions)); } else if (firstItem.IsFolder) { let sortBy = null; - let sortOrder = null; if (options.shuffle) { sortBy = 'Random'; } else if (firstItem.Type !== 'BoxSet') { - sortBy = sortOptions.sortBy; - sortOrder = sortOptions.sortOrder; + sortBy = 'SortName'; } promise = getItemsForPlayback(serverId, mergePlaybackQueries({ ParentId: firstItem.Id, @@ -1892,7 +1874,6 @@ class PlaybackManager { Recursive: true, // These are pre-sorted SortBy: sortBy, - SortOrder: sortOrder, MediaTypes: 'Audio,Video' }, queryOptions)); } else if (firstItem.Type === 'Episode' && items.length === 1 && getPlayer(firstItem, options).supportsProgress !== false) { diff --git a/src/components/shortcuts.js b/src/components/shortcuts.js index 70bf264fc..0fca127af 100644 --- a/src/components/shortcuts.js +++ b/src/components/shortcuts.js @@ -180,7 +180,7 @@ function executeAction(card, target, action) { const itemsContainer = dom.parentWithClass(card, 'itemsContainer'); - const sortParentId = 'items-' + (item.IsFolder ? item.Id : itemsContainer.getAttribute('data-parentid')) + '-Folder'; + const sortParentId = 'items-' + (item.IsFolder ? item.Id : itemsContainer?.getAttribute('data-parentid')) + '-Folder'; const serverId = item.ServerId; const type = item.Type; @@ -211,7 +211,7 @@ function executeAction(card, target, action) { ids: [playableItemId], startPositionTicks: startPositionTicks, serverId: serverId, - sortOptions: userSettings.getSortValues(sortParentId) + queryOptions: userSettings.getSortValuesLegacy(sortParentId, 'SortName') }); } else { console.warn('Unable to play item', item); diff --git a/src/controllers/list.js b/src/controllers/list.js index ded9d921e..31f3d5000 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -728,7 +728,7 @@ class ItemsView { playbackManager.play({ items: [currentItem], autoplay: true, - sortOptions: values + queryOptions: values }); } else { getItems(self, self.params, currentItem, null, 0, 300).then(function (result) { @@ -962,7 +962,7 @@ class ItemsView { getSortValues() { const basekey = this.getSettingsKey(); - return userSettings.getSortValues(basekey); + return userSettings.getSortValuesLegacy(basekey, this.getDefaultSortBy()); } getDefaultSortBy() { diff --git a/src/scripts/settings/userSettings.js b/src/scripts/settings/userSettings.js index 26fc2100e..339da9687 100644 --- a/src/scripts/settings/userSettings.js +++ b/src/scripts/settings/userSettings.js @@ -624,15 +624,28 @@ export class UserSettings { } /** - * Gets the current sort values + * Gets the current sort values (Legacy - Non-JSON) + * (old views such as list.js [Photos] will + * use this one) + * @param {string} key - Filter key. + * @return {Object} sortOptions object + */ + getSortValuesLegacy(key, defaultSortBy) { + return { + sortBy: this.getFilter(key + '-sortby') || defaultSortBy, + sortOrder: this.getFilter(key + '-sortorder') === 'Descending' ? 'Descending' : 'Ascending' + }; + } + + /** + * Gets the current sort values (JSON) + * (new views such as MoviesView will use + * this one) * @param {string} key - Filter key. * @return {Object} sortOptions object */ getSortValues(key) { - return { - sortBy: this.getFilter(key + '-sortby'), - sortOrder: this.getFilter(key + '-sortorder') === 'Descending' ? 'Descending' : 'Ascending' - }; + return this.loadQuerySettings(key, {}); } } @@ -684,4 +697,5 @@ export const customCss = currentSettings.customCss.bind(currentSettings); export const disableCustomCss = currentSettings.disableCustomCss.bind(currentSettings); export const getSavedView = currentSettings.getSavedView.bind(currentSettings); export const saveViewSetting = currentSettings.saveViewSetting.bind(currentSettings); +export const getSortValuesLegacy = currentSettings.getSortValuesLegacy.bind(currentSettings); export const getSortValues = currentSettings.getSortValues.bind(currentSettings); From 4488a586a45e60f2ec75357cd234d7f83d76ad7d Mon Sep 17 00:00:00 2001 From: MrK Date: Wed, 20 Sep 2023 22:50:01 +0100 Subject: [PATCH 07/74] Removed unneeded calls to getSortValues on playbackManager calls that only play 1 item --- src/components/itemContextMenu.js | 28 +--------------------------- src/controllers/list.js | 4 +--- 2 files changed, 2 insertions(+), 30 deletions(-) diff --git a/src/components/itemContextMenu.js b/src/components/itemContextMenu.js index fe01437b9..db742eda5 100644 --- a/src/components/itemContextMenu.js +++ b/src/components/itemContextMenu.js @@ -569,29 +569,6 @@ function deleteSeriesTimer(apiClient, item, resolve, command) { }); } -function getSettingsKey(item) { - if (item.IsFolder) { - return 'Folder'; - } - const itemType = item.MediaType; - switch (itemType) { - case 'Movie': - case 'BoxSet': - case 'Video': - return 'movies'; - case 'Audio': - return 'songs'; - case 'MusicAlbum': - return 'musicalbums'; - case 'MusicArtist': - return 'musicartists'; - case 'MusicGenre': - return 'genres'; - case 'MusicPlaylist': - return 'musicplaylists'; - } -} - function play(item, resume, queue, queueNext) { let method = 'play'; if (queue) { @@ -614,12 +591,9 @@ function play(item, resume, queue, queueNext) { serverId: item.ServerId }); } else { - const sortParentId = item.IsFolder ? ('items-' + item.Id) : libraryMenu.getTopParentId() + '-' + getSettingsKey(item); - const sortValues = userSettings.getSortValues(sortParentId); playbackManager[method]({ items: [item], - startPositionTicks: startPosition, - queryOptions: sortValues + startPositionTicks: startPosition }); } } diff --git a/src/controllers/list.js b/src/controllers/list.js index 31f3d5000..1ab0bd338 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -722,13 +722,11 @@ class ItemsView { function play() { const currentItem = self.currentItem; - const values = self.getSortValues(); if (currentItem && !self.hasFilters) { playbackManager.play({ items: [currentItem], - autoplay: true, - queryOptions: values + autoplay: true }); } else { getItems(self, self.params, currentItem, null, 0, 300).then(function (result) { From af61ae047c79d1df8889812ebd5dbf8f23314d6a Mon Sep 17 00:00:00 2001 From: MrK Date: Wed, 20 Sep 2023 22:55:16 +0100 Subject: [PATCH 08/74] Added queryOptions to MusicGenre call on playbackmanager UserSettings added param to function comment --- src/components/playback/playbackmanager.js | 2 +- src/scripts/settings/userSettings.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 1981fdc57..0ff00b232 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -1850,7 +1850,7 @@ class PlaybackManager { Recursive: true, SortBy: options.shuffle ? 'Random' : 'SortName', MediaTypes: 'Audio' - })); + }, queryOptions)); } else if (firstItem.IsFolder && firstItem.CollectionType === 'homevideos') { promise = getItemsForPlayback(serverId, mergePlaybackQueries({ ParentId: firstItem.Id, diff --git a/src/scripts/settings/userSettings.js b/src/scripts/settings/userSettings.js index 339da9687..fe301463f 100644 --- a/src/scripts/settings/userSettings.js +++ b/src/scripts/settings/userSettings.js @@ -628,6 +628,7 @@ export class UserSettings { * (old views such as list.js [Photos] will * use this one) * @param {string} key - Filter key. + * @param {string} defaultSortBy - Default SortBy value. * @return {Object} sortOptions object */ getSortValuesLegacy(key, defaultSortBy) { From ef8d92309bc8770e4a0a7e1dc2b6269d45f95c82 Mon Sep 17 00:00:00 2001 From: MrK Date: Wed, 20 Sep 2023 23:10:09 +0100 Subject: [PATCH 09/74] Code cleanup Restoring "Play All" functionality --- src/components/shortcuts.js | 7 +++++-- src/controllers/list.js | 5 +++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/components/shortcuts.js b/src/components/shortcuts.js index 0fca127af..bcbf42a36 100644 --- a/src/components/shortcuts.js +++ b/src/components/shortcuts.js @@ -205,13 +205,16 @@ function executeAction(card, target, action) { }); } else if (action === 'play' || action === 'resume') { const startPositionTicks = parseInt(card.getAttribute('data-positionticks') || '0', 10); - + const sortValues = userSettings.getSortValuesLegacy(sortParentId, 'SortName'); if (playbackManager.canPlay(item)) { playbackManager.play({ ids: [playableItemId], startPositionTicks: startPositionTicks, serverId: serverId, - queryOptions: userSettings.getSortValuesLegacy(sortParentId, 'SortName') + queryOptions: { + SortBy: sortValues.sortBy, + SortOrder: sortValues.sortOrder + } }); } else { console.warn('Unable to play item', item); diff --git a/src/controllers/list.js b/src/controllers/list.js index 1ab0bd338..5370bdcd6 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -724,8 +724,13 @@ class ItemsView { const currentItem = self.currentItem; if (currentItem && !self.hasFilters) { + const values = self.getSortValues(); playbackManager.play({ items: [currentItem], + queryOptions: { + SortBy: values.sortBy, + SortOrder: values.sortOrder + }, autoplay: true }); } else { From c935ba9a2058aec7eac1d234e27b6fb9dcbde082 Mon Sep 17 00:00:00 2001 From: MrK Date: Thu, 21 Sep 2023 00:14:07 +0100 Subject: [PATCH 10/74] Removed unused imports --- src/components/itemContextMenu.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/itemContextMenu.js b/src/components/itemContextMenu.js index db742eda5..0ec982f15 100644 --- a/src/components/itemContextMenu.js +++ b/src/components/itemContextMenu.js @@ -9,8 +9,6 @@ import itemHelper from './itemHelper'; import { playbackManager } from './playback/playbackmanager'; import ServerConnections from './ServerConnections'; import toast from './toast/toast'; -import * as userSettings from '../scripts/settings/userSettings'; -import libraryMenu from '../scripts/libraryMenu'; export function getCommands(options) { const item = options.item; From 5d20523616eebb814b3b1361cceee27eee33a083 Mon Sep 17 00:00:00 2001 From: MrK Date: Sat, 23 Sep 2023 22:50:57 +0100 Subject: [PATCH 11/74] Reverting itemContextMenu changes to support folder/playlist ordering with the "Play" action Code cleanup --- src/components/itemContextMenu.js | 34 +++++++++++++++++++++- src/components/playback/playbackmanager.js | 2 +- src/components/shortcuts.js | 1 + 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/components/itemContextMenu.js b/src/components/itemContextMenu.js index 0ec982f15..ee5518e11 100644 --- a/src/components/itemContextMenu.js +++ b/src/components/itemContextMenu.js @@ -9,6 +9,8 @@ import itemHelper from './itemHelper'; import { playbackManager } from './playback/playbackmanager'; import ServerConnections from './ServerConnections'; import toast from './toast/toast'; +import * as userSettings from '../scripts/settings/userSettings'; +import libraryMenu from '../scripts/libraryMenu'; export function getCommands(options) { const item = options.item; @@ -567,6 +569,29 @@ function deleteSeriesTimer(apiClient, item, resolve, command) { }); } +function getSettingsKey(item) { + if (item.IsFolder) { + return 'Folder'; + } + const itemType = item.MediaType; + switch (itemType) { + case 'Movie': + case 'BoxSet': + case 'Video': + return 'movies'; + case 'Audio': + return 'songs'; + case 'MusicAlbum': + return 'musicalbums'; + case 'MusicArtist': + return 'musicartists'; + case 'MusicGenre': + return 'genres'; + case 'MusicPlaylist': + return 'musicplaylists'; + } +} + function play(item, resume, queue, queueNext) { let method = 'play'; if (queue) { @@ -589,9 +614,16 @@ function play(item, resume, queue, queueNext) { serverId: item.ServerId }); } else { + const sortParentId = item.IsFolder ? ('items-' + item.Id) : libraryMenu.getTopParentId() + '-' + getSettingsKey(item); + const sortValues = userSettings.getSortValues(sortParentId); + playbackManager[method]({ items: [item], - startPositionTicks: startPosition + startPositionTicks: startPosition, + queryOptions: { + SortBy: sortValues.sortBy, + SortOrder: sortValues.sortOrder + } }); } } diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 0ff00b232..e263a7284 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -1815,7 +1815,7 @@ class PlaybackManager { // Setting this to true may cause some incorrect sorting Recursive: false, MediaTypes: 'Photo,Video', - sortBy: options.shuffle ? 'Random' : 'SortName', + SortBy: options.shuffle ? 'Random' : 'SortName', Limit: UNLIMITED_ITEMS }, queryOptions)).then(function (result) { const playbackItems = result.Items; diff --git a/src/components/shortcuts.js b/src/components/shortcuts.js index bcbf42a36..58a7bffb0 100644 --- a/src/components/shortcuts.js +++ b/src/components/shortcuts.js @@ -206,6 +206,7 @@ function executeAction(card, target, action) { } else if (action === 'play' || action === 'resume') { const startPositionTicks = parseInt(card.getAttribute('data-positionticks') || '0', 10); const sortValues = userSettings.getSortValuesLegacy(sortParentId, 'SortName'); + if (playbackManager.canPlay(item)) { playbackManager.play({ ids: [playableItemId], From fb77e19da793d51cbf9e2068f524bcba966c5aa2 Mon Sep 17 00:00:00 2001 From: Freako <65329453+Goku-04@users.noreply.github.com> Date: Mon, 2 Oct 2023 18:28:45 +0530 Subject: [PATCH 12/74] Directly return boolean value instead of returning it from ternary operator --- .../components/library/GenresSectionContainer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/experimental/components/library/GenresSectionContainer.tsx b/src/apps/experimental/components/library/GenresSectionContainer.tsx index 74f57782b..3295be54d 100644 --- a/src/apps/experimental/components/library/GenresSectionContainer.tsx +++ b/src/apps/experimental/components/library/GenresSectionContainer.tsx @@ -70,8 +70,8 @@ const GenresSectionContainer: FC = ({ centerText: true, cardLayout: false, shape: itemType === BaseItemKind.MusicAlbum ? 'overflowSquare' : 'overflowPortrait', - showParentTitle: itemType === BaseItemKind.MusicAlbum ? true : false, - showYear: itemType === BaseItemKind.MusicAlbum ? false : true + showParentTitle: (itemType === BaseItemKind.MusicAlbum), + showYear: !(itemType === BaseItemKind.MusicAlbum) }} />; }; From 0fe536a7e2c86a13d47dc5948837dba30b6d2552 Mon Sep 17 00:00:00 2001 From: Freako <65329453+Goku-04@users.noreply.github.com> Date: Mon, 2 Oct 2023 23:19:40 +0530 Subject: [PATCH 13/74] Replace !(===) with !== --- .../experimental/components/library/GenresSectionContainer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/experimental/components/library/GenresSectionContainer.tsx b/src/apps/experimental/components/library/GenresSectionContainer.tsx index 3295be54d..9945fd51e 100644 --- a/src/apps/experimental/components/library/GenresSectionContainer.tsx +++ b/src/apps/experimental/components/library/GenresSectionContainer.tsx @@ -71,7 +71,7 @@ const GenresSectionContainer: FC = ({ cardLayout: false, shape: itemType === BaseItemKind.MusicAlbum ? 'overflowSquare' : 'overflowPortrait', showParentTitle: (itemType === BaseItemKind.MusicAlbum), - showYear: !(itemType === BaseItemKind.MusicAlbum) + showYear: (itemType !== BaseItemKind.MusicAlbum) }} />; }; From d62a36a708869ca859d5e146edebb1bff1e1c78e Mon Sep 17 00:00:00 2001 From: MrK Date: Mon, 2 Oct 2023 23:25:57 +0100 Subject: [PATCH 14/74] itemContextMenu only supports folders and using parentId instead for lists Revert line change on playbackmanager.js --- src/components/itemContextMenu.js | 28 ++-------------------- src/components/playback/playbackmanager.js | 2 +- 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/src/components/itemContextMenu.js b/src/components/itemContextMenu.js index ee5518e11..89ef6b3d2 100644 --- a/src/components/itemContextMenu.js +++ b/src/components/itemContextMenu.js @@ -10,7 +10,6 @@ import { playbackManager } from './playback/playbackmanager'; import ServerConnections from './ServerConnections'; import toast from './toast/toast'; import * as userSettings from '../scripts/settings/userSettings'; -import libraryMenu from '../scripts/libraryMenu'; export function getCommands(options) { const item = options.item; @@ -569,29 +568,6 @@ function deleteSeriesTimer(apiClient, item, resolve, command) { }); } -function getSettingsKey(item) { - if (item.IsFolder) { - return 'Folder'; - } - const itemType = item.MediaType; - switch (itemType) { - case 'Movie': - case 'BoxSet': - case 'Video': - return 'movies'; - case 'Audio': - return 'songs'; - case 'MusicAlbum': - return 'musicalbums'; - case 'MusicArtist': - return 'musicartists'; - case 'MusicGenre': - return 'genres'; - case 'MusicPlaylist': - return 'musicplaylists'; - } -} - function play(item, resume, queue, queueNext) { let method = 'play'; if (queue) { @@ -614,8 +590,8 @@ function play(item, resume, queue, queueNext) { serverId: item.ServerId }); } else { - const sortParentId = item.IsFolder ? ('items-' + item.Id) : libraryMenu.getTopParentId() + '-' + getSettingsKey(item); - const sortValues = userSettings.getSortValues(sortParentId); + const sortParentId = 'items-' + (item.IsFolder ? item.Id : item.ParentId) + '-Folder'; + const sortValues = userSettings.getSortValuesLegacy(sortParentId); playbackManager[method]({ items: [item], diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index e263a7284..a546933ea 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -1814,8 +1814,8 @@ class PlaybackManager { Filters: 'IsNotFolder', // Setting this to true may cause some incorrect sorting Recursive: false, - MediaTypes: 'Photo,Video', SortBy: options.shuffle ? 'Random' : 'SortName', + MediaTypes: 'Photo,Video', Limit: UNLIMITED_ITEMS }, queryOptions)).then(function (result) { const playbackItems = result.Items; From a3eebd3a6ee2334207e24ae09578609579c85890 Mon Sep 17 00:00:00 2001 From: Freako <65329453+Goku-04@users.noreply.github.com> Date: Wed, 4 Oct 2023 12:26:18 +0530 Subject: [PATCH 15/74] Update src/apps/experimental/components/library/GenresSectionContainer.tsx Remove parentheses Co-authored-by: Bill Thornton --- .../components/library/GenresSectionContainer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/experimental/components/library/GenresSectionContainer.tsx b/src/apps/experimental/components/library/GenresSectionContainer.tsx index 9945fd51e..2ff0a10eb 100644 --- a/src/apps/experimental/components/library/GenresSectionContainer.tsx +++ b/src/apps/experimental/components/library/GenresSectionContainer.tsx @@ -70,8 +70,8 @@ const GenresSectionContainer: FC = ({ centerText: true, cardLayout: false, shape: itemType === BaseItemKind.MusicAlbum ? 'overflowSquare' : 'overflowPortrait', - showParentTitle: (itemType === BaseItemKind.MusicAlbum), - showYear: (itemType !== BaseItemKind.MusicAlbum) + showParentTitle: itemType === BaseItemKind.MusicAlbum, + showYear: itemType !== BaseItemKind.MusicAlbum }} />; }; From ad5bcb6c8d3f9fa073a6178e6c3602d52eb834d2 Mon Sep 17 00:00:00 2001 From: MrK Date: Thu, 5 Oct 2023 22:49:35 +0100 Subject: [PATCH 16/74] Removed unused method --- src/scripts/settings/userSettings.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/scripts/settings/userSettings.js b/src/scripts/settings/userSettings.js index fe301463f..f95f508e7 100644 --- a/src/scripts/settings/userSettings.js +++ b/src/scripts/settings/userSettings.js @@ -637,17 +637,6 @@ export class UserSettings { sortOrder: this.getFilter(key + '-sortorder') === 'Descending' ? 'Descending' : 'Ascending' }; } - - /** - * Gets the current sort values (JSON) - * (new views such as MoviesView will use - * this one) - * @param {string} key - Filter key. - * @return {Object} sortOptions object - */ - getSortValues(key) { - return this.loadQuerySettings(key, {}); - } } export const currentSettings = new UserSettings; @@ -699,4 +688,3 @@ export const disableCustomCss = currentSettings.disableCustomCss.bind(currentSet export const getSavedView = currentSettings.getSavedView.bind(currentSettings); export const saveViewSetting = currentSettings.saveViewSetting.bind(currentSettings); export const getSortValuesLegacy = currentSettings.getSortValuesLegacy.bind(currentSettings); -export const getSortValues = currentSettings.getSortValues.bind(currentSettings); From 4dcb0fa658458f77f43563e9f098831fffb49aba Mon Sep 17 00:00:00 2001 From: TelepathicWalrus Date: Fri, 4 Aug 2023 17:45:59 +0100 Subject: [PATCH 17/74] Add options for album gain --- src/components/playbackSettings/playbackSettings.js | 4 ++-- .../playbackSettings/playbackSettings.template.html | 13 +++++++++++-- src/plugins/htmlAudioPlayer/plugin.js | 5 ++++- src/scripts/settings/userSettings.js | 10 +++++----- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/components/playbackSettings/playbackSettings.js b/src/components/playbackSettings/playbackSettings.js index 0e3a798b6..c152c4f21 100644 --- a/src/components/playbackSettings/playbackSettings.js +++ b/src/components/playbackSettings/playbackSettings.js @@ -173,7 +173,7 @@ function loadForm(context, user, userSettings, apiClient) { context.querySelector('.chkPlayDefaultAudioTrack').checked = user.Configuration.PlayDefaultAudioTrack || false; context.querySelector('.chkPreferFmp4HlsContainer').checked = userSettings.preferFmp4HlsContainer(); context.querySelector('.chkEnableCinemaMode').checked = userSettings.enableCinemaMode(); - context.querySelector('.chkEnableAudioNormalization').checked = userSettings.enableAudioNormalization(); + context.querySelector('#selectAudioNormalization').checked = userSettings.audioNormalization(); context.querySelector('.chkEnableNextVideoOverlay').checked = userSettings.enableNextVideoInfoOverlay(); context.querySelector('.chkRememberAudioSelections').checked = user.Configuration.RememberAudioSelections || false; context.querySelector('.chkRememberSubtitleSelections').checked = user.Configuration.RememberSubtitleSelections || false; @@ -218,7 +218,7 @@ function saveUser(context, user, userSettingsInstance, apiClient) { user.Configuration.EnableNextEpisodeAutoPlay = context.querySelector('.chkEpisodeAutoPlay').checked; userSettingsInstance.preferFmp4HlsContainer(context.querySelector('.chkPreferFmp4HlsContainer').checked); userSettingsInstance.enableCinemaMode(context.querySelector('.chkEnableCinemaMode').checked); - userSettingsInstance.enableAudioNormalization(context.querySelector('.chkEnableAudioNormalization').checked); + userSettingsInstance.audioNormalization(context.querySelector('#selectAudioNormalization').checked); userSettingsInstance.enableNextVideoInfoOverlay(context.querySelector('.chkEnableNextVideoOverlay').checked); user.Configuration.RememberAudioSelections = context.querySelector('.chkRememberAudioSelections').checked; user.Configuration.RememberSubtitleSelections = context.querySelector('.chkRememberSubtitleSelections').checked; diff --git a/src/components/playbackSettings/playbackSettings.template.html b/src/components/playbackSettings/playbackSettings.template.html index 44dfe85e0..29803fad8 100644 --- a/src/components/playbackSettings/playbackSettings.template.html +++ b/src/components/playbackSettings/playbackSettings.template.html @@ -72,13 +72,22 @@ ${TabAdvanced} -
+
+ +
${StereoDownmixAlgorithmHelp}
+
+ +
From a01bfcef330e6bec0f36f552ddccce08096f9e4c Mon Sep 17 00:00:00 2001 From: LJQ Date: Fri, 13 Oct 2023 12:21:32 +0800 Subject: [PATCH 37/74] Change from 5 tabs to 20 spaces --- src/components/mediainfo/mediainfo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/mediainfo/mediainfo.js b/src/components/mediainfo/mediainfo.js index f0f9dd9a7..a6bfcf715 100644 --- a/src/components/mediainfo/mediainfo.js +++ b/src/components/mediainfo/mediainfo.js @@ -183,7 +183,7 @@ export function getMediaInfoHtml(item, options = {}) { if (item.EndDate) { try { const endYear = datetime.toLocaleString(datetime.parseISO8601Date(item.EndDate).getFullYear(), { useGrouping: false }); - /* At this point, text will contain only the start year */ + /* At this point, text will contain only the start year */ if (endYear !== text) { text += ` - ${endYear}`; } From e6828eeee8e8ba5e95e40b20621a54fe1dc7cdb8 Mon Sep 17 00:00:00 2001 From: Ranbeer Date: Sat, 14 Oct 2023 20:35:55 +0530 Subject: [PATCH 38/74] remove linter errors --- src/components/guide/guide.js | 2 +- src/components/listview/listview.js | 2 +- src/components/playback/playersettingsmenu.js | 2 +- src/controllers/itemDetails/index.js | 4 ++-- src/elements/emby-checkbox/emby-checkbox.js | 2 +- src/elements/emby-scrollbuttons/ScrollButtons.tsx | 4 ++-- src/scripts/browserDeviceProfile.js | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/guide/guide.js b/src/components/guide/guide.js index 76c54693f..97c8bff2c 100644 --- a/src/components/guide/guide.js +++ b/src/components/guide/guide.js @@ -291,7 +291,7 @@ function Guide(options) { showPremiereIndicator: allowIndicators && userSettings.get('guide-indicator-premiere') !== 'false', showNewIndicator: allowIndicators && userSettings.get('guide-indicator-new') !== 'false', showRepeatIndicator: allowIndicators && userSettings.get('guide-indicator-repeat') === 'true', - showEpisodeTitle: layoutManager.tv ? false : true + showEpisodeTitle: !layoutManager.tv }; apiClient.getLiveTvChannels(channelQuery).then(function (channelsResult) { diff --git a/src/components/listview/listview.js b/src/components/listview/listview.js index 1a230c31e..4c05be198 100644 --- a/src/components/listview/listview.js +++ b/src/components/listview/listview.js @@ -177,7 +177,7 @@ export function getListViewHtml(options) { const isLargeStyle = options.imageSize === 'large'; const enableOverview = options.enableOverview; - const clickEntireItem = layoutManager.tv ? true : false; + const clickEntireItem = layoutManager.tv; const outerTagName = clickEntireItem ? 'button' : 'div'; const enableSideMediaInfo = options.enableSideMediaInfo != null ? options.enableSideMediaInfo : true; diff --git a/src/components/playback/playersettingsmenu.js b/src/components/playback/playersettingsmenu.js index e0acde509..4afaa53a7 100644 --- a/src/components/playback/playersettingsmenu.js +++ b/src/components/playback/playersettingsmenu.js @@ -46,7 +46,7 @@ function showQualityMenu(player, btn) { const bitrate = parseInt(id, 10); if (bitrate !== selectedBitrate) { playbackManager.setMaxStreamingBitrate({ - enableAutomaticBitrateDetection: bitrate ? false : true, + enableAutomaticBitrateDetection: !!bitrate, maxBitrate: bitrate }, player); } diff --git a/src/controllers/itemDetails/index.js b/src/controllers/itemDetails/index.js index 4efe69e78..123b3c309 100644 --- a/src/controllers/itemDetails/index.js +++ b/src/controllers/itemDetails/index.js @@ -1374,8 +1374,8 @@ function renderChildren(page, item) { items: result.Items, showIndexNumber: false, enableOverview: true, - enablePlayedButton: layoutManager.mobile ? false : true, - infoButton: layoutManager.mobile ? false : true, + enablePlayedButton: !layoutManager.mobile, + infoButton: !layoutManager.mobile, imageSize: 'large', enableSideMediaInfo: false, highlight: false, diff --git a/src/elements/emby-checkbox/emby-checkbox.js b/src/elements/emby-checkbox/emby-checkbox.js index 2be4237d2..6fed51fe2 100644 --- a/src/elements/emby-checkbox/emby-checkbox.js +++ b/src/elements/emby-checkbox/emby-checkbox.js @@ -21,7 +21,7 @@ function onKeyDown(e) { } } -const enableRefreshHack = browser.tizen || browser.orsay || browser.operaTv || browser.web0s ? true : false; +const enableRefreshHack = browser.tizen || browser.orsay || browser.operaTv || browser.web0s; function forceRefresh(loading) { const elem = this.parentNode; diff --git a/src/elements/emby-scrollbuttons/ScrollButtons.tsx b/src/elements/emby-scrollbuttons/ScrollButtons.tsx index aaeb9bc23..a23eb7afc 100644 --- a/src/elements/emby-scrollbuttons/ScrollButtons.tsx +++ b/src/elements/emby-scrollbuttons/ScrollButtons.tsx @@ -67,7 +67,7 @@ const ScrollButtons: FC = ({ scrollerFactoryRef, scrollState className='emby-scrollbuttons-button btnPrev' onClick={triggerScrollLeft} icon='chevron_left' - disabled={localeScrollPos > 0 ? false : true} + disabled={!localeScrollPos > 0} /> = ({ scrollerFactoryRef, scrollState className='emby-scrollbuttons-button btnNext' onClick={triggerScrollRight} icon='chevron_right' - disabled={scrollState.scrollWidth > 0 && localeScrollPos + scrollState.scrollSize >= scrollState.scrollWidth ? true : false} + disabled={scrollState.scrollWidth > 0 && localeScrollPos + scrollState.scrollSize >= scrollState.scrollWidth} /> ); diff --git a/src/scripts/browserDeviceProfile.js b/src/scripts/browserDeviceProfile.js index f6289522f..afa8c8df7 100644 --- a/src/scripts/browserDeviceProfile.js +++ b/src/scripts/browserDeviceProfile.js @@ -692,7 +692,7 @@ export default function (options) { profile.TranscodingProfiles = []; - const hlsBreakOnNonKeyFrames = browser.iOS || browser.osx || browser.edge || !canPlayNativeHls() ? true : false; + const hlsBreakOnNonKeyFrames = browser.iOS || browser.osx || browser.edge || !canPlayNativeHls(); if (canPlayHls() && browser.enableHlsAudio !== false) { profile.TranscodingProfiles.push({ From c727871922f941603b16111d4d6abfb7dc632399 Mon Sep 17 00:00:00 2001 From: Ranbeer Date: Sat, 14 Oct 2023 20:44:30 +0530 Subject: [PATCH 39/74] modified: ScrollButtons.tsx --- src/elements/emby-scrollbuttons/ScrollButtons.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/elements/emby-scrollbuttons/ScrollButtons.tsx b/src/elements/emby-scrollbuttons/ScrollButtons.tsx index a23eb7afc..411bee1a9 100644 --- a/src/elements/emby-scrollbuttons/ScrollButtons.tsx +++ b/src/elements/emby-scrollbuttons/ScrollButtons.tsx @@ -67,7 +67,7 @@ const ScrollButtons: FC = ({ scrollerFactoryRef, scrollState className='emby-scrollbuttons-button btnPrev' onClick={triggerScrollLeft} icon='chevron_left' - disabled={!localeScrollPos > 0} + disabled={!(localeScrollPos > 0)} /> Date: Sat, 14 Oct 2023 20:56:28 +0530 Subject: [PATCH 40/74] replace (!!) with (!) Co-authored-by: Dmitry Lyzo <56478732+dmitrylyzo@users.noreply.github.com> --- src/components/playback/playersettingsmenu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/playback/playersettingsmenu.js b/src/components/playback/playersettingsmenu.js index 4afaa53a7..9f9f54d56 100644 --- a/src/components/playback/playersettingsmenu.js +++ b/src/components/playback/playersettingsmenu.js @@ -46,7 +46,7 @@ function showQualityMenu(player, btn) { const bitrate = parseInt(id, 10); if (bitrate !== selectedBitrate) { playbackManager.setMaxStreamingBitrate({ - enableAutomaticBitrateDetection: !!bitrate, + enableAutomaticBitrateDetection: !bitrate, maxBitrate: bitrate }, player); } From 63ffa27c2c56043228b5a9adaa3f3179f5a8c615 Mon Sep 17 00:00:00 2001 From: Freako <65329453+Goku-04@users.noreply.github.com> Date: Sat, 14 Oct 2023 21:12:32 +0530 Subject: [PATCH 41/74] Update ScrollButtons.tsx --- src/elements/emby-scrollbuttons/ScrollButtons.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/elements/emby-scrollbuttons/ScrollButtons.tsx b/src/elements/emby-scrollbuttons/ScrollButtons.tsx index 411bee1a9..87aa27d78 100644 --- a/src/elements/emby-scrollbuttons/ScrollButtons.tsx +++ b/src/elements/emby-scrollbuttons/ScrollButtons.tsx @@ -67,7 +67,7 @@ const ScrollButtons: FC = ({ scrollerFactoryRef, scrollState className='emby-scrollbuttons-button btnPrev' onClick={triggerScrollLeft} icon='chevron_left' - disabled={!(localeScrollPos > 0)} + disabled={localeScrollPos <= 0} /> Date: Mon, 9 Oct 2023 13:59:26 -0400 Subject: [PATCH 42/74] Change fallback fonts help text to link documentation --- src/strings/en-us.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 46ac58695..1ba80e7df 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -1624,7 +1624,7 @@ "HeaderSelectFallbackFontPath": "Select Fallback Font Folder Path", "HeaderSelectFallbackFontPathHelp": "Browse or enter the path of the fallback font folder to use for rendering ASS/SSA subtitles.", "LabelFallbackFontPath": "Fallback font folder path", - "LabelFallbackFontPathHelp": "Specify a path containing fallback fonts for rendering ASS/SSA subtitles. The maximum allowed total font size is 20 MB. Lightweight and web-friendly font formats such as woff2 are recommended.", + "LabelFallbackFontPathHelp": "Specify a path containing fallback fonts for rendering subtitles for some clients. The maximum allowed total font size is 20 MB. Please refer to the Jellyfin documentation on fonts for more info.", "EnableFallbackFont": "Enable fallback fonts", "EnableFallbackFontHelp": "Enable custom alternate fonts. This can avoid the problem of incorrect subtitle rendering.", "AspectRatioCover": "Cover", From 359e168acea940ef51b609f7517b20f6fc654919 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Mon, 16 Oct 2023 01:38:22 -0400 Subject: [PATCH 43/74] Use icon url from client capabilities --- src/components/cardbuilder/cardBuilder.js | 2 +- .../homesections/sections/libraryButtons.ts | 2 +- src/controllers/dashboard/dashboard.js | 2 +- src/controllers/dashboard/devices/devices.js | 2 +- src/controllers/dashboard/library.js | 2 +- src/scripts/libraryMenu.js | 2 +- .../imagehelper.js => utils/image.ts} | 19 +++++++++++-------- 7 files changed, 17 insertions(+), 14 deletions(-) rename src/{scripts/imagehelper.js => utils/image.ts} (80%) diff --git a/src/components/cardbuilder/cardBuilder.js b/src/components/cardbuilder/cardBuilder.js index 6d33700ca..c1c746006 100644 --- a/src/components/cardbuilder/cardBuilder.js +++ b/src/components/cardbuilder/cardBuilder.js @@ -11,8 +11,8 @@ import browser from 'scripts/browser'; import datetime from 'scripts/datetime'; import dom from 'scripts/dom'; import globalize from 'scripts/globalize'; -import imageHelper from 'scripts/imagehelper'; import { getBackdropShape, getPortraitShape, getSquareShape } from 'utils/card'; +import imageHelper from 'utils/image'; import { randomInt } from 'utils/number'; import focusManager from '../focusManager'; diff --git a/src/components/homesections/sections/libraryButtons.ts b/src/components/homesections/sections/libraryButtons.ts index 06656c343..fc5c48166 100644 --- a/src/components/homesections/sections/libraryButtons.ts +++ b/src/components/homesections/sections/libraryButtons.ts @@ -4,7 +4,7 @@ import escapeHtml from 'escape-html'; import imageLoader from 'components/images/imageLoader'; import { appRouter } from 'components/router/appRouter'; import globalize from 'scripts/globalize'; -import imageHelper from 'scripts/imagehelper'; +import imageHelper from 'utils/image'; function getLibraryButtonsHtml(items: BaseItemDto[]) { let html = ''; diff --git a/src/controllers/dashboard/dashboard.js b/src/controllers/dashboard/dashboard.js index bae3880f2..30f37764b 100644 --- a/src/controllers/dashboard/dashboard.js +++ b/src/controllers/dashboard/dashboard.js @@ -12,7 +12,7 @@ import playMethodHelper from '../../components/playback/playmethodhelper'; import cardBuilder from '../../components/cardbuilder/cardBuilder'; import imageLoader from '../../components/images/imageLoader'; import ActivityLog from '../../components/activitylog'; -import imageHelper from '../../scripts/imagehelper'; +import imageHelper from '../../utils/image'; import indicators from '../../components/indicators/indicators'; import '../../components/listview/listview.scss'; import '../../elements/emby-button/emby-button'; diff --git a/src/controllers/dashboard/devices/devices.js b/src/controllers/dashboard/devices/devices.js index c62571a1b..33ca6bfb0 100644 --- a/src/controllers/dashboard/devices/devices.js +++ b/src/controllers/dashboard/devices/devices.js @@ -3,7 +3,7 @@ import cardBuilder from '../../../components/cardbuilder/cardBuilder'; import loading from '../../../components/loading/loading'; import dom from '../../../scripts/dom'; import globalize from '../../../scripts/globalize'; -import imageHelper from '../../../scripts/imagehelper'; +import imageHelper from '../../../utils/image'; import { formatDistanceToNow } from 'date-fns'; import { getLocaleWithSuffix } from '../../../utils/dateFnsLocale.ts'; import '../../../elements/emby-button/emby-button'; diff --git a/src/controllers/dashboard/library.js b/src/controllers/dashboard/library.js index 62d932996..987169ecd 100644 --- a/src/controllers/dashboard/library.js +++ b/src/controllers/dashboard/library.js @@ -5,7 +5,7 @@ import loading from '../../components/loading/loading'; import libraryMenu from '../../scripts/libraryMenu'; import globalize from '../../scripts/globalize'; import dom from '../../scripts/dom'; -import imageHelper from '../../scripts/imagehelper'; +import imageHelper from '../../utils/image'; import '../../components/cardbuilder/card.scss'; import '../../elements/emby-itemrefreshindicator/emby-itemrefreshindicator'; import Dashboard, { pageClassOn, pageIdOn } from '../../utils/dashboard'; diff --git a/src/scripts/libraryMenu.js b/src/scripts/libraryMenu.js index f90ece9d7..ce105dbec 100644 --- a/src/scripts/libraryMenu.js +++ b/src/scripts/libraryMenu.js @@ -12,7 +12,7 @@ import { pluginManager } from '../components/pluginManager'; import groupSelectionMenu from '../plugins/syncPlay/ui/groupSelectionMenu'; import browser from './browser'; import globalize from './globalize'; -import imageHelper from './imagehelper'; +import imageHelper from '../utils/image'; import { getMenuLinks } from '../scripts/settings/webSettings'; import Dashboard, { pageClassOn } from '../utils/dashboard'; import ServerConnections from '../components/ServerConnections'; diff --git a/src/scripts/imagehelper.js b/src/utils/image.ts similarity index 80% rename from src/scripts/imagehelper.js rename to src/utils/image.ts index 052c68111..553420422 100644 --- a/src/scripts/imagehelper.js +++ b/src/utils/image.ts @@ -1,7 +1,10 @@ +import type { DeviceInfo } from '@jellyfin/sdk/lib/generated-client/models/device-info'; +import type { SessionInfo } from '@jellyfin/sdk/lib/generated-client/models/session-info'; + const BASE_DEVICE_IMAGE_URL = 'assets/img/devices/'; // audit note: this module is expected to return safe text for use in HTML -function getWebDeviceIcon(browser) { +function getWebDeviceIcon(browser: string | null | undefined) { switch (browser) { case 'Opera': case 'Opera TV': @@ -31,8 +34,8 @@ function getWebDeviceIcon(browser) { } } -export function getDeviceIcon(device) { - switch (device.AppName || device.Client) { +export function getDeviceIcon(info: DeviceInfo | SessionInfo) { + switch ((info as DeviceInfo).AppName || (info as SessionInfo).Client) { case 'Samsung Smart TV': return BASE_DEVICE_IMAGE_URL + 'samsung.svg'; case 'Xbox One': @@ -58,13 +61,13 @@ export function getDeviceIcon(device) { case 'Finamp': return BASE_DEVICE_IMAGE_URL + 'finamp.svg'; case 'Jellyfin Web': - return getWebDeviceIcon(device.Name || device.DeviceName); + return getWebDeviceIcon((info as DeviceInfo).Name || (info as SessionInfo).DeviceName); default: - return BASE_DEVICE_IMAGE_URL + 'other.svg'; + return info.Capabilities?.IconUrl || BASE_DEVICE_IMAGE_URL + 'other.svg'; } } -export function getLibraryIcon(library) { +export function getLibraryIcon(library: string | null | undefined) { switch (library) { case 'movies': return 'video_library'; @@ -94,6 +97,6 @@ export function getLibraryIcon(library) { } export default { - getDeviceIcon: getDeviceIcon, - getLibraryIcon: getLibraryIcon + getDeviceIcon, + getLibraryIcon }; From 6ee7be956759a177b1712bf53a00d1e95acef538 Mon Sep 17 00:00:00 2001 From: felix920506 Date: Mon, 16 Oct 2023 01:41:51 -0400 Subject: [PATCH 44/74] Move link into code --- src/controllers/dashboard/encodingsettings.html | 4 +++- src/strings/en-us.json | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/controllers/dashboard/encodingsettings.html b/src/controllers/dashboard/encodingsettings.html index 278d95dba..af2d4eb6d 100644 --- a/src/controllers/dashboard/encodingsettings.html +++ b/src/controllers/dashboard/encodingsettings.html @@ -254,7 +254,9 @@ -
${LabelFallbackFontPathHelp}
+