Add max parental rating and max days recent filters to configuration
This commit is contained in:
@@ -15,6 +15,8 @@ namespace Jellyfin.Plugin.MediaBarEnhanced.Configuration
|
|||||||
public int MaxMovies { get; set; } = 15;
|
public int MaxMovies { get; set; } = 15;
|
||||||
public int MaxTvShows { get; set; } = 15;
|
public int MaxTvShows { get; set; } = 15;
|
||||||
public int MaxItems { get; set; } = 500;
|
public int MaxItems { get; set; } = 500;
|
||||||
|
public int MaxParentalRating { get; set; } = 0;
|
||||||
|
public int MaxDaysRecent { get; set; } = 0;
|
||||||
public int PreloadCount { get; set; } = 3;
|
public int PreloadCount { get; set; } = 3;
|
||||||
public int FadeTransitionDuration { get; set; } = 500;
|
public int FadeTransitionDuration { get; set; } = 500;
|
||||||
public int MaxPaginationDots { get; set; } = 15;
|
public int MaxPaginationDots { get; set; } = 15;
|
||||||
|
|||||||
@@ -356,7 +356,7 @@
|
|||||||
mobile).</div>
|
mobile).</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 class="sectionTitle">Content Sorting</h2>
|
<h2 class="sectionTitle">Content Sorting and Filtering</h2>
|
||||||
<div class="selectContainer">
|
<div class="selectContainer">
|
||||||
<label class="selectLabel" for="SortBy">Sort By</label>
|
<label class="selectLabel" for="SortBy">Sort By</label>
|
||||||
<select is="emby-select" id="SortBy" name="SortBy"
|
<select is="emby-select" id="SortBy" name="SortBy"
|
||||||
@@ -387,6 +387,16 @@
|
|||||||
<b>Note:</b> Sorting settings apply to both Server content and Custom IDs. 'Original'
|
<b>Note:</b> Sorting settings apply to both Server content and Custom IDs. 'Original'
|
||||||
preserves Custom List order.
|
preserves Custom List order.
|
||||||
</div>
|
</div>
|
||||||
|
<div class="inputContainer">
|
||||||
|
<label class="inputLabel inputLabelUnfocused" for="MaxParentalRating">Max Parental Rating (Age Limit)</label>
|
||||||
|
<input is="emby-input" type="number" id="MaxParentalRating" name="MaxParentalRating" />
|
||||||
|
<div class="fieldDescription">Items exceeding this age rating will not be shown. Leave blank for no limit. Examples: 12, 16, 18.</div>
|
||||||
|
</div>
|
||||||
|
<div class="inputContainer">
|
||||||
|
<label class="inputLabel inputLabelUnfocused" for="MaxDaysRecent">Max Days Recent</label>
|
||||||
|
<input is="emby-input" type="number" id="MaxDaysRecent" name="MaxDaysRecent" />
|
||||||
|
<div class="fieldDescription">Only show items added in the last X days. Leave blank for no limit. Example: 30.</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2 class="sectionTitle">Content Limits</h2>
|
<h2 class="sectionTitle">Content Limits</h2>
|
||||||
<p>Leave a setting blank to use the default value.</p>
|
<p>Leave a setting blank to use the default value.</p>
|
||||||
@@ -505,7 +515,8 @@
|
|||||||
'EnableSeasonalContent', 'EnableClientSideSettings', 'SortBy', 'SortOrder',
|
'EnableSeasonalContent', 'EnableClientSideSettings', 'SortBy', 'SortOrder',
|
||||||
'PreferLocalTrailers', 'ApplyLimitsToCustomIds', 'SeasonalSections',
|
'PreferLocalTrailers', 'ApplyLimitsToCustomIds', 'SeasonalSections',
|
||||||
'PreferLocalBackdrops', 'RandomizeThemeVideos', 'RandomizeLocalTrailers',
|
'PreferLocalBackdrops', 'RandomizeThemeVideos', 'RandomizeLocalTrailers',
|
||||||
'IncludeWatchedContent', 'ShowPaginationDots'
|
'IncludeWatchedContent', 'ShowPaginationDots', 'MaxParentalRating',
|
||||||
|
'MaxDaysRecent'
|
||||||
];
|
];
|
||||||
|
|
||||||
// Manual mapping for MediaBarIsEnabled -> IsEnabled, to avoid conflicts with other plugins
|
// Manual mapping for MediaBarIsEnabled -> IsEnabled, to avoid conflicts with other plugins
|
||||||
@@ -609,7 +620,8 @@
|
|||||||
'EnableSeasonalContent', 'EnableClientSideSettings', 'SortBy', 'SortOrder',
|
'EnableSeasonalContent', 'EnableClientSideSettings', 'SortBy', 'SortOrder',
|
||||||
'PreferLocalTrailers', 'ApplyLimitsToCustomIds', 'SeasonalSections',
|
'PreferLocalTrailers', 'ApplyLimitsToCustomIds', 'SeasonalSections',
|
||||||
'PreferLocalBackdrops', 'RandomizeThemeVideos', 'RandomizeLocalTrailers',
|
'PreferLocalBackdrops', 'RandomizeThemeVideos', 'RandomizeLocalTrailers',
|
||||||
'IncludeWatchedContent', 'ShowPaginationDots'
|
'IncludeWatchedContent', 'ShowPaginationDots', 'MaxParentalRating',
|
||||||
|
'MaxDaysRecent'
|
||||||
];
|
];
|
||||||
|
|
||||||
keys.forEach(function (key) {
|
keys.forEach(function (key) {
|
||||||
|
|||||||
@@ -814,7 +814,6 @@
|
|||||||
@media (max-width: 400px) {
|
@media (max-width: 400px) {
|
||||||
.button-container {
|
.button-container {
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
/* top: calc(50% + 27vh); */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.play-button,
|
.play-button,
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ const CONFIG = {
|
|||||||
fadeTransitionDuration: 500,
|
fadeTransitionDuration: 500,
|
||||||
maxPaginationDots: 15,
|
maxPaginationDots: 15,
|
||||||
showPaginationDots: true,
|
showPaginationDots: true,
|
||||||
|
maxParentalRating: null,
|
||||||
|
maxDaysRecent: null,
|
||||||
slideAnimationEnabled: true,
|
slideAnimationEnabled: true,
|
||||||
enableVideoBackdrop: true,
|
enableVideoBackdrop: true,
|
||||||
useSponsorBlock: true,
|
useSponsorBlock: true,
|
||||||
@@ -1111,13 +1113,26 @@ const ApiUtils = {
|
|||||||
|
|
||||||
// Filter by isPlayed=False unless IncludeWatchedContent is enabled
|
// Filter by isPlayed=False unless IncludeWatchedContent is enabled
|
||||||
const playedFilter = CONFIG.includeWatchedContent ? '' : '&isPlayed=False';
|
const playedFilter = CONFIG.includeWatchedContent ? '' : '&isPlayed=False';
|
||||||
|
|
||||||
|
let parentalFilter = '';
|
||||||
|
if (CONFIG.maxParentalRating) {
|
||||||
|
parentalFilter = `&MaxOfficialRating=${CONFIG.maxParentalRating}`;
|
||||||
|
}
|
||||||
|
|
||||||
const response = await fetch(
|
let dateFilter = '';
|
||||||
`${STATE.jellyfinData.serverAddress}/Items?IncludeItemTypes=Movie,Series&Recursive=true&hasOverview=true&imageTypes=Logo,Backdrop&${sortParams}${playedFilter}&enableUserData=true&Limit=${CONFIG.maxItems}&fields=Id`,
|
if (CONFIG.maxDaysRecent) {
|
||||||
{
|
const pastDate = new Date();
|
||||||
headers: this.getAuthHeaders(),
|
pastDate.setDate(pastDate.getDate() - CONFIG.maxDaysRecent);
|
||||||
}
|
dateFilter = `&minDateLastSaved=${pastDate.toISOString()}`;
|
||||||
);
|
}
|
||||||
|
|
||||||
|
const fetchItems = async (currentDateFilter) => {
|
||||||
|
const url = `${STATE.jellyfinData.serverAddress}/Items?IncludeItemTypes=Movie,Series&Recursive=true&hasOverview=true&imageTypes=Logo,Backdrop&${sortParams}${playedFilter}${parentalFilter}${currentDateFilter}&enableUserData=true&Limit=${CONFIG.maxItems}&fields=Id,DateCreated`;
|
||||||
|
const resp = await fetch(url, { headers: this.getAuthHeaders() });
|
||||||
|
return resp;
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = await fetchItems(dateFilter);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
console.error("🎬 Media Bar:",
|
console.error("🎬 Media Bar:",
|
||||||
@@ -1126,12 +1141,32 @@ const ApiUtils = {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
let data = await response.json();
|
||||||
const items = data.Items || [];
|
let items = data.Items || [];
|
||||||
|
|
||||||
console.log("🎬 Media Bar:",
|
// Local exact DateCreated filter: minDateLastSaved pulls items that were merely modified recently (e.g. metadata updates)
|
||||||
`Successfully fetched ${items.length} random items from server`
|
// explicitly discard them if their actual DateCreated is older than X days
|
||||||
);
|
if (CONFIG.maxDaysRecent && dateFilter !== '') {
|
||||||
|
const pastDate = new Date();
|
||||||
|
pastDate.setDate(pastDate.getDate() - CONFIG.maxDaysRecent);
|
||||||
|
items = items.filter(item => {
|
||||||
|
if (!item.DateCreated) return true;
|
||||||
|
return new Date(item.DateCreated) >= pastDate;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: If we have a date filter but no items are returned, try again without it
|
||||||
|
if (items.length === 0 && dateFilter !== '') {
|
||||||
|
console.warn("🎬 Media Bar:", `No items found within the last ${CONFIG.maxDaysRecent} days. Falling back to random fetching.`);
|
||||||
|
response = await fetchItems('');
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
data = await response.json();
|
||||||
|
items = data.Items || [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("🎬 Media Bar:", `Successfully fetched ${items.length} random items from server`);
|
||||||
|
|
||||||
return items.map((item) => item.Id);
|
return items.map((item) => item.Id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user