fix: download options filter uses user preferences
This commit is contained in:
@@ -6,6 +6,9 @@ import { Controller } from '@hotwired/stimulus';
|
|||||||
*/
|
*/
|
||||||
/* stimulusFetch: 'lazy' */
|
/* stimulusFetch: 'lazy' */
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
|
H264_CODECS = ['h264', 'h.264', 'x264']
|
||||||
|
H265_CODECS = ['h265', 'h.265', 'x265', 'hevc']
|
||||||
|
|
||||||
static values = {
|
static values = {
|
||||||
title: String,
|
title: String,
|
||||||
tmdbId: String,
|
tmdbId: String,
|
||||||
@@ -37,7 +40,53 @@ export default class extends Controller {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
listTargetConnected(target) {
|
async filter(activeFilter) {
|
||||||
// console.log(target);
|
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;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ export default class extends Controller {
|
|||||||
"provider": "",
|
"provider": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
userPreferences = []
|
|
||||||
|
|
||||||
static outlets = ['movie-results', 'tv-results']
|
static outlets = ['movie-results', 'tv-results']
|
||||||
static targets = ['resolution', 'codec', 'language', 'provider', 'season', 'selectAll', 'downloadSelected']
|
static targets = ['resolution', 'codec', 'language', 'provider', 'season', 'selectAll', 'downloadSelected']
|
||||||
static values = {
|
static values = {
|
||||||
@@ -30,7 +28,6 @@ export default class extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async connect() {
|
async connect() {
|
||||||
this.userPreferences = await(await fetch('/api/user/preferences/values')).json();
|
|
||||||
if (this.mediaTypeValue === "tvshows") {
|
if (this.mediaTypeValue === "tvshows") {
|
||||||
this.activeFilter['season'] = 1;
|
this.activeFilter['season'] = 1;
|
||||||
}
|
}
|
||||||
@@ -53,33 +50,11 @@ export default class extends Controller {
|
|||||||
this.addLanguages(option, option.dataset);
|
this.addLanguages(option, option.dataset);
|
||||||
this.addProviders(option, option.dataset);
|
this.addProviders(option, option.dataset);
|
||||||
})
|
})
|
||||||
}
|
await this.filter();
|
||||||
|
|
||||||
addResolutions(resolutions) {
|
|
||||||
this.resolutionTarget.innerHTML = '<option value="">n/a</option>';
|
|
||||||
this.resolutionTarget.innerHTML += resolutions.preferenceOptions
|
|
||||||
.map((resolution) => {
|
|
||||||
if ('resolution' in this.userPreferences) {
|
|
||||||
return '<option value="' + resolution.name.toLowerCase() + '" selected>' + resolution.name + '</option>';
|
|
||||||
}
|
|
||||||
return '<option value="' + resolution.name.toLowerCase() + '">' + resolution.name + '</option>';
|
|
||||||
})
|
|
||||||
.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
addCodecs(codecs) {
|
|
||||||
this.codecTarget.innerHTML = '<option value="">n/a</option>';
|
|
||||||
this.codecTarget.innerHTML += codecs.preferenceOptions
|
|
||||||
.map((codec) => {
|
|
||||||
if ('codec' in this.userPreferences) {
|
|
||||||
return '<option value="' + codec.name.toLowerCase() + '" selected>' + codec.name + '</option>';
|
|
||||||
}
|
|
||||||
return '<option value="' + codec.name.toLowerCase() + '">' + codec.name + '</option>'
|
|
||||||
})
|
|
||||||
.join();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addLanguages(option, props) {
|
addLanguages(option, props) {
|
||||||
|
console.log('herey');
|
||||||
const languages = Object.assign([], JSON.parse(props['languages']));
|
const languages = Object.assign([], JSON.parse(props['languages']));
|
||||||
languages.forEach((language) => {
|
languages.forEach((language) => {
|
||||||
if (!this.languages.includes(language)) {
|
if (!this.languages.includes(language)) {
|
||||||
@@ -118,79 +93,13 @@ export default class extends Controller {
|
|||||||
|
|
||||||
if ("movies" === this.mediaTypeValue) {
|
if ("movies" === this.mediaTypeValue) {
|
||||||
results = this.movieResultsOutlets;
|
results = this.movieResultsOutlets;
|
||||||
|
await results.forEach((list) => list.filter(this.activeFilter));
|
||||||
|
|
||||||
} else if ("tvshows" === this.mediaTypeValue) {
|
} else if ("tvshows" === this.mediaTypeValue) {
|
||||||
results = this.tvResultsOutlets;
|
results = this.tvResultsOutlets;
|
||||||
this.activeFilter.season = this.seasonTarget.value;
|
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() {
|
uncheckSelectAllBtn() {
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import { Controller } from '@hotwired/stimulus';
|
|||||||
*/
|
*/
|
||||||
/* stimulusFetch: 'lazy' */
|
/* stimulusFetch: 'lazy' */
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
|
H264_CODECS = ['h264', 'h.264', 'x264']
|
||||||
|
H265_CODECS = ['h265', 'h.265', 'x265', 'hevc']
|
||||||
|
|
||||||
static values = {
|
static values = {
|
||||||
title: String,
|
title: String,
|
||||||
tmdbId: String,
|
tmdbId: String,
|
||||||
@@ -52,9 +55,11 @@ export default class extends Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setInActive() {
|
async setInActive() {
|
||||||
this.activeValue = false;
|
this.activeValue = false;
|
||||||
|
// if (true === this.hasEpisodeSelectorTarget()) {
|
||||||
this.episodeSelectorTarget.checked = false;
|
this.episodeSelectorTarget.checked = false;
|
||||||
|
// }
|
||||||
this.element.classList.add('hidden');
|
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;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,5 @@ final class Filter
|
|||||||
->toArray();
|
->toArray();
|
||||||
$this->userPreferences = Map::from($this->security->getUser()->getUserPreferenceValues())
|
$this->userPreferences = Map::from($this->security->getUser()->getUserPreferenceValues())
|
||||||
->toArray();
|
->toArray();
|
||||||
// dd($this->userPreferences);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,7 +190,18 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
|||||||
{
|
{
|
||||||
return Map::from($this->userPreferences)
|
return Map::from($this->userPreferences)
|
||||||
->rekey(fn(UserPreference $userPreference) => $userPreference->getPreference()->getId())
|
->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();
|
->toArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,9 @@
|
|||||||
>
|
>
|
||||||
<option value="">n/a</option>
|
<option value="">n/a</option>
|
||||||
{% for option in this.preferences['resolution'] %}
|
{% for option in this.preferences['resolution'] %}
|
||||||
<option value="{{ option.name|lower }}">{{ option.name }}</option>
|
<option value="{{ option.value }}"
|
||||||
|
{{ option.value == this.userPreferences['resolution'] ? 'selected' }}
|
||||||
|
>{{ option.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
@@ -24,7 +26,9 @@
|
|||||||
<select id="codec" data-result-filter-target="codec" class="px-1 py-0.5 bg-stone-100 text-sm text-gray-800 rounded-md">
|
<select id="codec" data-result-filter-target="codec" class="px-1 py-0.5 bg-stone-100 text-sm text-gray-800 rounded-md">
|
||||||
<option value="">n/a</option>
|
<option value="">n/a</option>
|
||||||
{% for option in this.preferences['codec'] %}
|
{% for option in this.preferences['codec'] %}
|
||||||
<option value="{{ option.name|lower }}">{{ option.name }}</option>
|
<option value="{{ option.value }}"
|
||||||
|
{{ option.value == this.userPreferences['codec'] ? 'selected' }}
|
||||||
|
>{{ option.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
Reference in New Issue
Block a user