From b59069551a61d5b775e1809eee0591e31d53f79c Mon Sep 17 00:00:00 2001 From: Brock H Caldwell Date: Wed, 30 Apr 2025 15:53:10 -0500 Subject: [PATCH] fix: download options filter uses user preferences --- .../controllers/movie_results_controller.js | 53 ++++++++- .../controllers/result_filter_controller.js | 101 +----------------- assets/controllers/tv_results_controller.js | 71 +++++++++++- src/Twig/Components/Filter.php | 1 - src/User/Framework/Entity/User.php | 13 ++- templates/components/Filter.html.twig | 8 +- 6 files changed, 144 insertions(+), 103 deletions(-) diff --git a/assets/controllers/movie_results_controller.js b/assets/controllers/movie_results_controller.js index 7d2ca27..b630515 100644 --- a/assets/controllers/movie_results_controller.js +++ b/assets/controllers/movie_results_controller.js @@ -6,6 +6,9 @@ import { Controller } from '@hotwired/stimulus'; */ /* stimulusFetch: 'lazy' */ export default class extends Controller { + H264_CODECS = ['h264', 'h.264', 'x264'] + H265_CODECS = ['h265', 'h.265', 'x265', 'hevc'] + static values = { title: String, tmdbId: String, @@ -37,7 +40,53 @@ export default class extends Controller { return true; } - listTargetConnected(target) { - // console.log(target); + async filter(activeFilter) { + let firstIncluded = true; + let count = 0; + let selectedCount = 0; + + this.options.forEach((option) => { + const props = { + "resolution": option.querySelector('#resolution').textContent.trim(), + "codec": option.querySelector('#codec').textContent.trim(), + "provider": option.querySelector('#provider').textContent.trim(), + "languages": JSON.parse(option.dataset['languages']), + } + + let include = true; + option.classList.remove('hidden'); + + for (let [key, value] of Object.entries(activeFilter)) { + if (value === "" || key === "season") { + continue; + } + if (key === "codec" && value === "h264") { + if (!this.H264_CODECS.includes(props[key].toLowerCase())) { + include = false; + } + } else if (key === "codec" && value === "h265") { + if (!this.H265_CODECS.includes(props[key].toLowerCase())) { + include = false; + } + } else if (key === "language") { + if (!props["languages"].includes(value)) { + include = false; + } + } else if (props[key] !== value) { + include = false; + } + } + + if (false === include) { + option.classList.add('hidden'); + } else if (true === firstIncluded) { + count = 1; + selectedCount = selectedCount + 1; + option.querySelector('input[type="checkbox"]').checked = true; + firstIncluded = false; + } else { + count = count + 1; + } + }); } } diff --git a/assets/controllers/result_filter_controller.js b/assets/controllers/result_filter_controller.js index a1e5c63..4eabf6e 100644 --- a/assets/controllers/result_filter_controller.js +++ b/assets/controllers/result_filter_controller.js @@ -20,8 +20,6 @@ export default class extends Controller { "provider": "", } - userPreferences = [] - static outlets = ['movie-results', 'tv-results'] static targets = ['resolution', 'codec', 'language', 'provider', 'season', 'selectAll', 'downloadSelected'] static values = { @@ -30,7 +28,6 @@ export default class extends Controller { } async connect() { - this.userPreferences = await(await fetch('/api/user/preferences/values')).json(); if (this.mediaTypeValue === "tvshows") { this.activeFilter['season'] = 1; } @@ -53,33 +50,11 @@ export default class extends Controller { this.addLanguages(option, option.dataset); this.addProviders(option, option.dataset); }) - } - - addResolutions(resolutions) { - this.resolutionTarget.innerHTML = ''; - this.resolutionTarget.innerHTML += resolutions.preferenceOptions - .map((resolution) => { - if ('resolution' in this.userPreferences) { - return ''; - } - return ''; - }) - .join(); - } - - addCodecs(codecs) { - this.codecTarget.innerHTML = ''; - this.codecTarget.innerHTML += codecs.preferenceOptions - .map((codec) => { - if ('codec' in this.userPreferences) { - return ''; - } - return '' - }) - .join(); + await this.filter(); } addLanguages(option, props) { + console.log('herey'); const languages = Object.assign([], JSON.parse(props['languages'])); languages.forEach((language) => { if (!this.languages.includes(language)) { @@ -118,79 +93,13 @@ export default class extends Controller { if ("movies" === this.mediaTypeValue) { results = this.movieResultsOutlets; + await results.forEach((list) => list.filter(this.activeFilter)); + } else if ("tvshows" === this.mediaTypeValue) { results = this.tvResultsOutlets; this.activeFilter.season = this.seasonTarget.value; + await results.forEach((list) => list.filter(this.activeFilter, currentSeason, this.seasonTarget.value)); } - - const filterOperation = async (resultList, currentSeason) => { - if ("tvshows" === this.mediaTypeValue && currentSeason !== this.activeFilter['season']) { - if (resultList.seasonValue === this.seasonTarget.value) { - await resultList.setActive(); - } else { - resultList.setInActive(); - } - } - - if (false === resultList.isActive()) { - return; - } - - let firstIncluded = true; - let count = 0; - let selectedCount = 0; - - resultList.options.forEach((option) => { - const props = { - "resolution": option.querySelector('#resolution').textContent.trim(), - "codec": option.querySelector('#codec').textContent.trim(), - "provider": option.querySelector('#provider').textContent.trim(), - "languages": JSON.parse(option.dataset['languages']), - } - - let include = true; - option.classList.remove('hidden'); - - for (let [key, value] of Object.entries(this.activeFilter)) { - if (value === "" || key === "season") { - continue; - } - if (key === "codec" && value === "h264") { - if (!this.H264_CODECS.includes(props[key].toLowerCase())) { - include = false; - } - } else if (key === "codec" && value === "h265") { - if (!this.H265_CODECS.includes(props[key].toLowerCase())) { - include = false; - } - } else if (key === "language") { - if (!props["languages"].includes(value)) { - include = false; - } - } else if (props[key] !== value) { - include = false; - } - } - - if (false === include) { - option.classList.add('hidden'); - } else if (true === firstIncluded) { - count = 1; - selectedCount = selectedCount + 1; - option.querySelector('input[type="checkbox"]').checked = true; - firstIncluded = false; - } else { - count = count + 1; - } - - if ("tvshows" === this.mediaTypeValue) { - resultList.countTarget.innerText = count; - } - }); - - } - - await results.forEach((list) => filterOperation(list, currentSeason)); } uncheckSelectAllBtn() { diff --git a/assets/controllers/tv_results_controller.js b/assets/controllers/tv_results_controller.js index 805aff2..52a94f1 100644 --- a/assets/controllers/tv_results_controller.js +++ b/assets/controllers/tv_results_controller.js @@ -6,6 +6,9 @@ import { Controller } from '@hotwired/stimulus'; */ /* stimulusFetch: 'lazy' */ export default class extends Controller { + H264_CODECS = ['h264', 'h.264', 'x264'] + H265_CODECS = ['h265', 'h.265', 'x265', 'hevc'] + static values = { title: String, tmdbId: String, @@ -52,9 +55,11 @@ export default class extends Controller { } } - setInActive() { + async setInActive() { this.activeValue = false; + // if (true === this.hasEpisodeSelectorTarget()) { this.episodeSelectorTarget.checked = false; + // } this.element.classList.add('hidden'); } @@ -88,4 +93,68 @@ export default class extends Controller { } }) } + + async filter(activeFilter, currentSeason, newSeason) { + if (currentSeason !== activeFilter['season']) { + if (this.seasonValue === newSeason) { + await this.setActive(); + } else { + await this.setInActive(); + } + } + + if (false === this.isActive()) { + return; + } + + let firstIncluded = true; + let count = 0; + let selectedCount = 0; + + this.options.forEach((option) => { + const props = { + "resolution": option.querySelector('#resolution').textContent.trim(), + "codec": option.querySelector('#codec').textContent.trim(), + "provider": option.querySelector('#provider').textContent.trim(), + "languages": JSON.parse(option.dataset['languages']), + } + + let include = true; + option.classList.remove('hidden'); + + for (let [key, value] of Object.entries(activeFilter)) { + if (value === "" || key === "season") { + continue; + } + if (key === "codec" && value === "h264") { + if (!this.H264_CODECS.includes(props[key].toLowerCase())) { + include = false; + } + } else if (key === "codec" && value === "h265") { + if (!this.H265_CODECS.includes(props[key].toLowerCase())) { + include = false; + } + } else if (key === "language") { + if (!props["languages"].includes(value)) { + include = false; + } + } else if (props[key] !== value) { + include = false; + } + } + + if (false === include) { + option.classList.add('hidden'); + } else if (true === firstIncluded) { + count = 1; + selectedCount = selectedCount + 1; + option.querySelector('input[type="checkbox"]').checked = true; + firstIncluded = false; + } else { + count = count + 1; + } + + this.countTarget.innerText = count; + }); + } } diff --git a/src/Twig/Components/Filter.php b/src/Twig/Components/Filter.php index c63de8e..d7e135f 100644 --- a/src/Twig/Components/Filter.php +++ b/src/Twig/Components/Filter.php @@ -27,6 +27,5 @@ final class Filter ->toArray(); $this->userPreferences = Map::from($this->security->getUser()->getUserPreferenceValues()) ->toArray(); -// dd($this->userPreferences); } } diff --git a/src/User/Framework/Entity/User.php b/src/User/Framework/Entity/User.php index eb2eb91..233984a 100644 --- a/src/User/Framework/Entity/User.php +++ b/src/User/Framework/Entity/User.php @@ -190,7 +190,18 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface { return Map::from($this->userPreferences) ->rekey(fn(UserPreference $userPreference) => $userPreference->getPreference()->getId()) - ->map(fn(UserPreference $userPreference) => $userPreference->getPreferenceValue()) + ->map(function (UserPreference $userPreference) { + if (in_array($userPreference->getPreference()->getId(), ['language', 'provider'])) { + return $userPreference->getPreferenceValue(); + } + foreach ($userPreference->getPreference()->getPreferenceOptions() as $preferenceOption) { +// dd((int) $userPreference->getPreferenceValue(), $preferenceOption->getId(), $preferenceOption->getValue()); + if ($preferenceOption->getId() === (int) $userPreference->getPreferenceValue()) { + return $preferenceOption->getValue(); + } + } + return null; + }) ->toArray(); } } diff --git a/templates/components/Filter.html.twig b/templates/components/Filter.html.twig index 94dccff..8a297c5 100644 --- a/templates/components/Filter.html.twig +++ b/templates/components/Filter.html.twig @@ -15,7 +15,9 @@ > {% for option in this.preferences['resolution'] %} - + {% endfor %} @@ -24,7 +26,9 @@