From 9575977584da3f73ee10f543c08faf0f922ea891 Mon Sep 17 00:00:00 2001
From: ItsAllAboutTheCode <52703+ItsAllAboutTheCode@users.noreply.github.com>
Date: Mon, 17 Jun 2024 01:04:40 -0500
Subject: [PATCH 1/6] Added support to shuffle theme media playback
The ThemeMusicPlayer has been updated to support the "SortName" and "Random" Sort By options to allow sorting theme media for playback by either the sorted name or at random depending on the number of items.
The "Ascending" and "Descending" Sort Order options were also added, which adds support to playback the theme media in reverse order of the sorted name. This is only supported for the "SortName" option
Updated the Display settings for both the current and experimental display mode to add the "Theme media sort by" and "Theme media sort order" drop-down which allows users to modify the ThemeMusicPlayer sort options.
The Display Settings are only shown if either the "Theme songs" or "Theme videos" checkboxes are checked.
This is the implementation for the feature request located https://features.jellyfin.org/posts/2740/select-audio-from-the-theme-music-folder-at-random
---
CONTRIBUTORS.md | 1 +
.../preferences/hooks/useDisplaySettings.ts | 4 +++
.../types/displaySettingsValues.ts | 2 ++
.../displaySettings/displaySettings.js | 29 ++++++++++++++++++-
.../displaySettings.template.html | 18 ++++++++++++
src/components/themeMediaPlayer.js | 21 +++++++++++++-
src/scripts/settings/userSettings.js | 29 +++++++++++++++++++
src/strings/en-us.json | 5 ++++
8 files changed, 107 insertions(+), 2 deletions(-)
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index f73bfe3d4e1..c79fa08ca97 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -94,6 +94,7 @@
- [iFraan](https://github.com/iFraan)
- [Ali](https://github.com/bu3alwa)
- [K. Kyle Puchkov](https://github.com/kepper104)
+- [ItsAllAboutTheCode](https://github.com/ItsAllAboutTheCode)
## Emby Contributors
diff --git a/src/apps/experimental/features/preferences/hooks/useDisplaySettings.ts b/src/apps/experimental/features/preferences/hooks/useDisplaySettings.ts
index 09e52b26863..f1660f97649 100644
--- a/src/apps/experimental/features/preferences/hooks/useDisplaySettings.ts
+++ b/src/apps/experimental/features/preferences/hooks/useDisplaySettings.ts
@@ -96,6 +96,8 @@ async function loadDisplaySettings({
maxDaysForNextUp: settings.maxDaysForNextUp(),
screensaver: settings.screensaver() || 'none',
screensaverInterval: settings.backdropScreensaverInterval(),
+ libraryThemeMediaSortBy: settings.themeMediaSortBy(),
+ libraryThemeMediaSortOrder: settings.themeMediaSortOrder(),
theme: settings.theme()
};
@@ -138,6 +140,8 @@ async function saveDisplaySettings({
userSettings.libraryPageSize(newDisplaySettings.libraryPageSize);
userSettings.maxDaysForNextUp(newDisplaySettings.maxDaysForNextUp);
userSettings.screensaver(normalizeValue(newDisplaySettings.screensaver));
+ userSettings.themeMediaSortBy(newDisplaySettings.libraryThemeMediaSortBy);
+ userSettings.themeMediaSortOrder(newDisplaySettings.libraryThemeMediaSortOrder);
userSettings.backdropScreensaverInterval(newDisplaySettings.screensaverInterval);
userSettings.theme(newDisplaySettings.theme);
diff --git a/src/apps/experimental/features/preferences/types/displaySettingsValues.ts b/src/apps/experimental/features/preferences/types/displaySettingsValues.ts
index a5e08d2dd99..c97a315d655 100644
--- a/src/apps/experimental/features/preferences/types/displaySettingsValues.ts
+++ b/src/apps/experimental/features/preferences/types/displaySettingsValues.ts
@@ -18,5 +18,7 @@ export interface DisplaySettingsValues {
maxDaysForNextUp: number;
screensaver: string;
screensaverInterval: number;
+ libraryThemeMediaSortBy: string;
+ libraryThemeMediaSortOrder: string;
theme: string;
}
diff --git a/src/components/displaySettings/displaySettings.js b/src/components/displaySettings/displaySettings.js
index 354ef54d099..77471acbd41 100644
--- a/src/components/displaySettings/displaySettings.js
+++ b/src/components/displaySettings/displaySettings.js
@@ -114,8 +114,16 @@ function loadForm(context, user, userSettings) {
context.querySelector('.chkDisplayMissingEpisodes').checked = user.Configuration.DisplayMissingEpisodes || false;
- context.querySelector('#chkThemeSong').checked = userSettings.enableThemeSongs();
+ const themeSongSelector = context.querySelector('#chkThemeSong');
+ themeSongSelector.checked = userSettings.enableThemeSongs();
context.querySelector('#chkThemeVideo').checked = userSettings.enableThemeVideos();
+
+ context.querySelector('#selectThemeMediaSortBy').value = userSettings.themeMediaSortBy();
+ context.querySelector('#selectThemeMediaSortOrder').value = userSettings.themeMediaSortOrder();
+
+ // Trigger initial change event to update the Theme Sort By / Theme Sort Order visibility
+ themeSongSelector.dispatchEvent(new CustomEvent('change', {}));
+
context.querySelector('#chkFadein').checked = userSettings.enableFastFadein();
context.querySelector('#chkBlurhash').checked = userSettings.enableBlurhash();
context.querySelector('#chkBackdrops').checked = userSettings.enableBackdrops();
@@ -150,6 +158,8 @@ function saveUser(context, user, userSettingsInstance, apiClient) {
userSettingsInstance.dateTimeLocale(context.querySelector('.selectDateTimeLocale').value);
userSettingsInstance.enableThemeSongs(context.querySelector('#chkThemeSong').checked);
+ userSettingsInstance.themeMediaSortBy(context.querySelector('#selectThemeMediaSortBy').value);
+ userSettingsInstance.themeMediaSortOrder(context.querySelector('#selectThemeMediaSortOrder').value);
userSettingsInstance.enableThemeVideos(context.querySelector('#chkThemeVideo').checked);
userSettingsInstance.theme(context.querySelector('#selectTheme').value);
userSettingsInstance.dashboardTheme(context.querySelector('#selectDashboardTheme').value);
@@ -216,6 +226,23 @@ function onSubmit(e) {
function embed(options, self) {
options.element.innerHTML = globalize.translateHtml(template, 'core');
options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self));
+ const updateThemeMediaSortShowState = function () {
+ const themeMediaElements = options.element.querySelectorAll('.themeMediaChecked');
+ const themeMediaEnabled = options.element.querySelector('#chkThemeSong').checked || options.element.querySelector('#chkThemeVideo').checked;
+ for (const themeMediaElement of themeMediaElements) {
+ if (themeMediaEnabled) {
+ themeMediaElement.classList.remove('hide');
+ } else {
+ themeMediaElement.classList.add('hide');
+ }
+ }
+ };
+
+ const themeSongSelector = options.element.querySelector('#chkThemeSong');
+ themeSongSelector.addEventListener('change', updateThemeMediaSortShowState);
+ const themeVideoSelector = options.element.querySelector('#chkThemeVideo');
+ themeVideoSelector.addEventListener('change', updateThemeMediaSortShowState);
+
if (options.enableSaveButton) {
options.element.querySelector('.btnSave').classList.remove('hide');
}
diff --git a/src/components/displaySettings/displaySettings.template.html b/src/components/displaySettings/displaySettings.template.html
index 1b5579b4c30..670e8ca1fd8 100644
--- a/src/components/displaySettings/displaySettings.template.html
+++ b/src/components/displaySettings/displaySettings.template.html
@@ -263,6 +263,24 @@
${EnableThemeVideosHelp}
+
+
+
+