fix: support missing/no-episodes library filters (API, UI, docs, tests)
This commit is contained in:
@@ -16,7 +16,7 @@ AniWorld.SeriesManager = (function() {
|
||||
// State
|
||||
let seriesData = [];
|
||||
let filteredSeriesData = [];
|
||||
let showMissingOnly = false;
|
||||
let filterMode = 'all'; // 'all' | 'missing_episodes' | 'no_episodes'
|
||||
let sortAlphabetical = false;
|
||||
|
||||
/**
|
||||
@@ -24,15 +24,16 @@ AniWorld.SeriesManager = (function() {
|
||||
*/
|
||||
function init() {
|
||||
bindEvents();
|
||||
updateFilterButtonUI();
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind UI events for filtering and sorting
|
||||
*/
|
||||
function bindEvents() {
|
||||
const missingOnlyBtn = document.getElementById('show-missing-only');
|
||||
if (missingOnlyBtn) {
|
||||
missingOnlyBtn.addEventListener('click', toggleMissingOnlyFilter);
|
||||
const filterBtn = document.getElementById('show-missing-only');
|
||||
if (filterBtn) {
|
||||
filterBtn.addEventListener('click', toggleFilterMode);
|
||||
}
|
||||
|
||||
const sortBtn = document.getElementById('sort-alphabetical');
|
||||
@@ -49,7 +50,10 @@ AniWorld.SeriesManager = (function() {
|
||||
try {
|
||||
AniWorld.UI.showLoading();
|
||||
|
||||
const response = await AniWorld.ApiClient.get(API.ANIME_LIST);
|
||||
const url = filterMode && filterMode !== 'all'
|
||||
? `${API.ANIME_LIST}?filter=${encodeURIComponent(filterMode)}`
|
||||
: API.ANIME_LIST;
|
||||
const response = await AniWorld.ApiClient.get(url);
|
||||
|
||||
if (!response) {
|
||||
return [];
|
||||
@@ -111,28 +115,28 @@ AniWorld.SeriesManager = (function() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle missing episodes only filter
|
||||
* Cycle through filter modes:
|
||||
* - all: Show all series
|
||||
* - missing_episodes: Show only series with missing episodes
|
||||
* - no_episodes: Show only series with zero downloaded episodes
|
||||
*/
|
||||
function toggleMissingOnlyFilter() {
|
||||
showMissingOnly = !showMissingOnly;
|
||||
async function toggleFilterMode() {
|
||||
const button = document.getElementById('show-missing-only');
|
||||
|
||||
button.setAttribute('data-active', showMissingOnly);
|
||||
button.classList.toggle('active', showMissingOnly);
|
||||
|
||||
const icon = button.querySelector('i');
|
||||
const text = button.querySelector('span');
|
||||
|
||||
if (showMissingOnly) {
|
||||
icon.className = 'fas fa-filter-circle-xmark';
|
||||
text.textContent = 'Show All Series';
|
||||
// Cycle through modes
|
||||
if (filterMode === 'all') {
|
||||
filterMode = 'missing_episodes';
|
||||
} else if (filterMode === 'missing_episodes') {
|
||||
filterMode = 'no_episodes';
|
||||
} else {
|
||||
icon.className = 'fas fa-filter';
|
||||
text.textContent = 'Missing Episodes Only';
|
||||
filterMode = 'all';
|
||||
}
|
||||
|
||||
applyFiltersAndSort();
|
||||
renderSeries();
|
||||
// Update button UI and reload list based on new filter.
|
||||
updateFilterButtonUI();
|
||||
await loadSeries();
|
||||
|
||||
// Clear selection when filter changes
|
||||
if (AniWorld.SelectionManager) {
|
||||
@@ -140,6 +144,34 @@ AniWorld.SeriesManager = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the filter button UI to reflect current filter mode
|
||||
*/
|
||||
function updateFilterButtonUI() {
|
||||
const button = document.getElementById('show-missing-only');
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
|
||||
const icon = button.querySelector('i');
|
||||
const text = button.querySelector('span');
|
||||
|
||||
const isActive = filterMode !== 'all';
|
||||
button.setAttribute('data-active', isActive);
|
||||
button.classList.toggle('active', isActive);
|
||||
|
||||
if (filterMode === 'missing_episodes') {
|
||||
icon.className = 'fas fa-filter';
|
||||
text.textContent = 'Missing Episodes Only';
|
||||
} else if (filterMode === 'no_episodes') {
|
||||
icon.className = 'fas fa-ban';
|
||||
text.textContent = 'No Episodes';
|
||||
} else {
|
||||
icon.className = 'fas fa-filter-circle-xmark';
|
||||
text.textContent = 'Show All Series';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle alphabetical sorting
|
||||
*/
|
||||
@@ -193,13 +225,6 @@ AniWorld.SeriesManager = (function() {
|
||||
}
|
||||
});
|
||||
|
||||
// Apply missing episodes filter
|
||||
if (showMissingOnly) {
|
||||
filtered = filtered.filter(function(serie) {
|
||||
return serie.missing_episodes > 0;
|
||||
});
|
||||
}
|
||||
|
||||
filteredSeriesData = filtered;
|
||||
}
|
||||
|
||||
@@ -212,9 +237,14 @@ AniWorld.SeriesManager = (function() {
|
||||
(seriesData.length > 0 ? seriesData : []);
|
||||
|
||||
if (dataToRender.length === 0) {
|
||||
const message = showMissingOnly ?
|
||||
'No series with missing episodes found.' :
|
||||
'No series found. Try searching for anime or rescanning your directory.';
|
||||
let message;
|
||||
if (filterMode === 'missing_episodes') {
|
||||
message = 'No series with missing episodes found.';
|
||||
} else if (filterMode === 'no_episodes') {
|
||||
message = 'No series with zero downloaded episodes found.';
|
||||
} else {
|
||||
message = 'No series found. Try searching for anime or rescanning your directory.';
|
||||
}
|
||||
|
||||
grid.innerHTML =
|
||||
'<div class="text-center" style="grid-column: 1 / -1; padding: 2rem;">' +
|
||||
|
||||
Reference in New Issue
Block a user