Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63be8214d0 | ||
|
|
99411afffd | ||
|
|
9510ae6ba7 | ||
|
|
2030538acc | ||
|
|
463e9ef424 |
@@ -35,5 +35,7 @@ namespace Jellyfin.Plugin.MediaBarEnhanced.Configuration
|
|||||||
public bool EnableSeasonalContent { get; set; } = false;
|
public bool EnableSeasonalContent { get; set; } = false;
|
||||||
public bool IsEnabled { get; set; } = true;
|
public bool IsEnabled { get; set; } = true;
|
||||||
public bool EnableClientSideSettings { get; set; } = false;
|
public bool EnableClientSideSettings { get; set; } = false;
|
||||||
|
public string SortBy { get; set; } = "Random";
|
||||||
|
public string SortOrder { get; set; } = "Ascending";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -274,6 +274,32 @@
|
|||||||
mobile).</div>
|
mobile).</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h2 class="sectionTitle">Content Sorting</h2>
|
||||||
|
<div class="selectContainer">
|
||||||
|
<label class="selectLabel" for="SortBy">Sort By</label>
|
||||||
|
<select is="emby-select" id="SortBy" name="SortBy" class="emby-select-withcolor emby-select">
|
||||||
|
<option value="Random">Random</option>
|
||||||
|
<option value="Original">Original (Custom List Order)</option>
|
||||||
|
<option value="PremiereDate">Premiere Date</option>
|
||||||
|
<option value="DateCreated">Date Created</option>
|
||||||
|
<option value="CommunityRating">Community Rating</option>
|
||||||
|
<option value="Name">Name</option>
|
||||||
|
<option value="Runtime">Runtime</option>
|
||||||
|
</select>
|
||||||
|
<div class="fieldDescription">Sort items by the selected criteria.</div>
|
||||||
|
</div>
|
||||||
|
<div class="selectContainer">
|
||||||
|
<label class="selectLabel" for="SortOrder">Sort Order</label>
|
||||||
|
<select is="emby-select" id="SortOrder" name="SortOrder" class="emby-select-withcolor emby-select">
|
||||||
|
<option value="Ascending">Ascending</option>
|
||||||
|
<option value="Descending">Descending</option>
|
||||||
|
</select>
|
||||||
|
<div class="fieldDescription">Sort items in Ascending or Descending order.</div>
|
||||||
|
</div>
|
||||||
|
<div class="fieldDescription" style="margin-bottom: 2em; color: #ffcc00;">
|
||||||
|
<b>Note:</b> Sorting settings apply to both Server content and Custom IDs. 'Original' preserves Custom List order.
|
||||||
|
</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>
|
||||||
<div class="inputContainer">
|
<div class="inputContainer">
|
||||||
@@ -370,7 +396,7 @@
|
|||||||
'WaitForTrailerToEnd', 'StartMuted', 'FullWidthVideo', 'EnableMobileVideo',
|
'WaitForTrailerToEnd', 'StartMuted', 'FullWidthVideo', 'EnableMobileVideo',
|
||||||
'ShowTrailerButton', 'AlwaysShowArrows', 'EnableKeyboardControls',
|
'ShowTrailerButton', 'AlwaysShowArrows', 'EnableKeyboardControls',
|
||||||
'EnableCustomMediaIds', 'CustomMediaIds', 'EnableLoadingScreen',
|
'EnableCustomMediaIds', 'CustomMediaIds', 'EnableLoadingScreen',
|
||||||
'EnableSeasonalContent', 'EnableClientSideSettings'
|
'EnableSeasonalContent', 'EnableClientSideSettings', 'SortBy', 'SortOrder'
|
||||||
];
|
];
|
||||||
|
|
||||||
keys.forEach(function (key) {
|
keys.forEach(function (key) {
|
||||||
@@ -419,7 +445,7 @@
|
|||||||
'WaitForTrailerToEnd', 'StartMuted', 'FullWidthVideo', 'EnableMobileVideo',
|
'WaitForTrailerToEnd', 'StartMuted', 'FullWidthVideo', 'EnableMobileVideo',
|
||||||
'ShowTrailerButton', 'AlwaysShowArrows', 'EnableKeyboardControls',
|
'ShowTrailerButton', 'AlwaysShowArrows', 'EnableKeyboardControls',
|
||||||
'EnableCustomMediaIds', 'CustomMediaIds', 'EnableLoadingScreen',
|
'EnableCustomMediaIds', 'CustomMediaIds', 'EnableLoadingScreen',
|
||||||
'EnableSeasonalContent', 'EnableClientSideSettings'
|
'EnableSeasonalContent', 'EnableClientSideSettings', 'SortBy', 'SortOrder'
|
||||||
];
|
];
|
||||||
|
|
||||||
keys.forEach(function (key) {
|
keys.forEach(function (key) {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<!-- <TreatWarningsAsErrors>false</TreatWarningsAsErrors> -->
|
<!-- <TreatWarningsAsErrors>false</TreatWarningsAsErrors> -->
|
||||||
<Title>Jellyfin Media Bar Enhanced Plugin</Title>
|
<Title>Jellyfin Media Bar Enhanced Plugin</Title>
|
||||||
<Authors>CodeDevMLH</Authors>
|
<Authors>CodeDevMLH</Authors>
|
||||||
<Version>1.5.0.4</Version>
|
<Version>1.5.0.6</Version>
|
||||||
<RepositoryUrl>https://github.com/CodeDevMLH/jellyfin-plugin-media-bar-enhanced</RepositoryUrl>
|
<RepositoryUrl>https://github.com/CodeDevMLH/jellyfin-plugin-media-bar-enhanced</RepositoryUrl>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ const CONFIG = {
|
|||||||
customMediaIds: "",
|
customMediaIds: "",
|
||||||
enableLoadingScreen: true,
|
enableLoadingScreen: true,
|
||||||
enableClientSideSettings: false,
|
enableClientSideSettings: false,
|
||||||
|
sortBy: "Random",
|
||||||
|
sortOrder: "Ascending",
|
||||||
};
|
};
|
||||||
|
|
||||||
// State management
|
// State management
|
||||||
@@ -460,6 +462,62 @@ waitForApiClientAndInitialize();
|
|||||||
* Utility functions for slide creation and management
|
* Utility functions for slide creation and management
|
||||||
*/
|
*/
|
||||||
const SlideUtils = {
|
const SlideUtils = {
|
||||||
|
/**
|
||||||
|
* Sorts items based on configuration
|
||||||
|
* @param {Array<Object>} items - Array of item objects
|
||||||
|
* @param {string} sortBy - Sort criteria
|
||||||
|
* @param {string} sortOrder - Sort order 'Ascending' or 'Descending'
|
||||||
|
* @returns {Array<Object>} Sorted array of items
|
||||||
|
*/
|
||||||
|
sortItems(items, sortBy, sortOrder) {
|
||||||
|
if (sortBy === 'Random' || sortBy === 'Original') {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
const simpleCompare = (a, b) => {
|
||||||
|
if (a < b) return -1;
|
||||||
|
if (a > b) return 1;
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const sorted = [...items].sort((a, b) => {
|
||||||
|
let valA, valB;
|
||||||
|
|
||||||
|
switch (sortBy) {
|
||||||
|
case 'DateCreated':
|
||||||
|
valA = new Date(a.DateCreated).getTime();
|
||||||
|
valB = new Date(b.DateCreated).getTime();
|
||||||
|
break;
|
||||||
|
case 'PremiereDate':
|
||||||
|
valA = new Date(a.PremiereDate).getTime();
|
||||||
|
valB = new Date(b.PremiereDate).getTime();
|
||||||
|
break;
|
||||||
|
case 'CommunityRating':
|
||||||
|
valA = a.CommunityRating || 0;
|
||||||
|
valB = b.CommunityRating || 0;
|
||||||
|
break;
|
||||||
|
case 'Runtime':
|
||||||
|
valA = a.RunTimeTicks || 0;
|
||||||
|
valB = b.RunTimeTicks || 0;
|
||||||
|
break;
|
||||||
|
case 'Name':
|
||||||
|
valA = (a.Name || '').toLowerCase();
|
||||||
|
valB = (b.Name || '').toLowerCase();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return simpleCompare(valA, valB);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (sortOrder === 'Descending') {
|
||||||
|
sorted.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
return sorted;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shuffles array elements randomly
|
* Shuffles array elements randomly
|
||||||
* @param {Array} array - Array to shuffle
|
* @param {Array} array - Array to shuffle
|
||||||
@@ -960,8 +1018,8 @@ const ApiUtils = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${STATE.jellyfinData.serverAddress}/Items/${itemId}`,
|
// `${STATE.jellyfinData.serverAddress}/Items/${itemId}`,
|
||||||
// `${STATE.jellyfinData.serverAddress}/Users/${STATE.jellyfinData.userId}/Items/${itemId}?Fields=Overview,RemoteTrailers,Genres,CommunityRating,CriticRating,OfficialRating,PremiereDate,RunTimeTicks,ProductionYear,MediaSources`,
|
`${STATE.jellyfinData.serverAddress}/Items/${itemId}?Fields=Overview,RemoteTrailers,Genres,CommunityRating,CriticRating,OfficialRating,PremiereDate,ProductionYear,MediaSources,RunTimeTicks`,
|
||||||
{
|
{
|
||||||
headers: this.getAuthHeaders(),
|
headers: this.getAuthHeaders(),
|
||||||
}
|
}
|
||||||
@@ -1033,8 +1091,16 @@ const ApiUtils = {
|
|||||||
|
|
||||||
console.log("Fetching random items from server...");
|
console.log("Fetching random items from server...");
|
||||||
|
|
||||||
|
let sortParams = `sortBy=${CONFIG.sortBy}`;
|
||||||
|
|
||||||
|
if (CONFIG.sortBy === 'Random' || CONFIG.sortBy === 'Original') {
|
||||||
|
sortParams = 'sortBy=Random';
|
||||||
|
} else {
|
||||||
|
sortParams += `&sortOrder=${CONFIG.sortOrder}`;
|
||||||
|
}
|
||||||
|
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${STATE.jellyfinData.serverAddress}/Items?IncludeItemTypes=Movie,Series&Recursive=true&hasOverview=true&imageTypes=Logo,Backdrop&sortBy=Random&isPlayed=False&enableUserData=true&Limit=${CONFIG.maxItems}&fields=Id`,
|
`${STATE.jellyfinData.serverAddress}/Items?IncludeItemTypes=Movie,Series&Recursive=true&hasOverview=true&imageTypes=Logo,Backdrop&${sortParams}&isPlayed=False&enableUserData=true&Limit=${CONFIG.maxItems}&fields=Id`,
|
||||||
{
|
{
|
||||||
headers: this.getAuthHeaders(),
|
headers: this.getAuthHeaders(),
|
||||||
}
|
}
|
||||||
@@ -2560,16 +2626,6 @@ const SlideshowManager = {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "ArrowUp":
|
|
||||||
case "ArrowDown":
|
|
||||||
setTimeout(() => {
|
|
||||||
const active = document.activeElement;
|
|
||||||
if (active && active !== document.body && active.id !== "slides-container") {
|
|
||||||
active.scrollIntoView({behavior: 'smooth', block: 'center'});
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case " ": // Space bar
|
case " ": // Space bar
|
||||||
this.togglePause();
|
this.togglePause();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -2784,10 +2840,28 @@ const SlideshowManager = {
|
|||||||
if (itemIds.length === 0) {
|
if (itemIds.length === 0) {
|
||||||
console.log("No custom list found, fetching random items from server...");
|
console.log("No custom list found, fetching random items from server...");
|
||||||
itemIds = await ApiUtils.fetchItemIdsFromServer();
|
itemIds = await ApiUtils.fetchItemIdsFromServer();
|
||||||
|
|
||||||
|
if (CONFIG.sortBy === 'Random') {
|
||||||
|
itemIds = SlideUtils.shuffleArray(itemIds);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Custom IDs
|
||||||
|
if (CONFIG.sortBy === 'Random') {
|
||||||
|
itemIds = SlideUtils.shuffleArray(itemIds);
|
||||||
|
} else if (CONFIG.sortBy !== 'Original') {
|
||||||
|
// Client-side sort required...
|
||||||
|
console.log(`Sorting ${itemIds.length} custom items by ${CONFIG.sortBy} ${CONFIG.sortOrder}`);
|
||||||
|
const itemsWithDetails = [];
|
||||||
|
for (const id of itemIds) {
|
||||||
|
const item = await ApiUtils.fetchItemDetails(id);
|
||||||
|
if (item) itemsWithDetails.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortedItems = SlideUtils.sortItems(itemsWithDetails, CONFIG.sortBy, CONFIG.sortOrder);
|
||||||
|
itemIds = sortedItems.map(i => i.Id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
itemIds = SlideUtils.shuffleArray(itemIds);
|
|
||||||
|
|
||||||
STATE.slideshow.itemIds = itemIds;
|
STATE.slideshow.itemIds = itemIds;
|
||||||
STATE.slideshow.totalItems = itemIds.length;
|
STATE.slideshow.totalItems = itemIds.length;
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,12 @@
|
|||||||
"imageUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/raw/branch/main/logo.png",
|
"imageUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/raw/branch/main/logo.png",
|
||||||
"versions": [
|
"versions": [
|
||||||
{
|
{
|
||||||
"version": "1.5.0.4",
|
"version": "1.5.0.6",
|
||||||
"changelog": "- fix: keyboard controls in TV mode \n- Update mediaBarEnhanced.js and mediaBarEnhanced.css with version 4.0.1 from original repo",
|
"changelog": "- fix: keyboard controls in TV mode\n- Add sorting options for content in configuration\n- Update mediaBarEnhanced.js and mediaBarEnhanced.css with version 4.0.1 from original repo",
|
||||||
"targetAbi": "10.11.0.0",
|
"targetAbi": "10.11.0.0",
|
||||||
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/releases/download/v1.5.0.4/Jellyfin.Plugin.MediaBarEnhanced.zip",
|
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/releases/download/v1.5.0.6/Jellyfin.Plugin.MediaBarEnhanced.zip",
|
||||||
"checksum": "4a9bf88fd4c7580a961b5fda0d3d3678",
|
"checksum": "c1c0736b06b3855523fe2eac25e6b34b",
|
||||||
"timestamp": "2026-02-08T01:32:39Z"
|
"timestamp": "2026-02-09T00:31:34Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"version": "1.3.0.3",
|
"version": "1.3.0.3",
|
||||||
|
|||||||
Reference in New Issue
Block a user