diff --git a/Jellyfin.Plugin.MediaBarEnhanced/Configuration/PluginConfiguration.cs b/Jellyfin.Plugin.MediaBarEnhanced/Configuration/PluginConfiguration.cs
index 7909786..e015864 100644
--- a/Jellyfin.Plugin.MediaBarEnhanced/Configuration/PluginConfiguration.cs
+++ b/Jellyfin.Plugin.MediaBarEnhanced/Configuration/PluginConfiguration.cs
@@ -18,6 +18,7 @@ namespace Jellyfin.Plugin.MediaBarEnhanced.Configuration
public int PreloadCount { get; set; } = 3;
public int FadeTransitionDuration { get; set; } = 500;
public int MaxPaginationDots { get; set; } = 15;
+ public bool ShowPaginationDots { get; set; } = true;
public bool SlideAnimationEnabled { get; set; } = true;
public bool EnableVideoBackdrop { get; set; } = true;
public bool UseSponsorBlock { get; set; } = true;
diff --git a/Jellyfin.Plugin.MediaBarEnhanced/Configuration/configPage.html b/Jellyfin.Plugin.MediaBarEnhanced/Configuration/configPage.html
index e3cb11b..ba64a44 100644
--- a/Jellyfin.Plugin.MediaBarEnhanced/Configuration/configPage.html
+++ b/Jellyfin.Plugin.MediaBarEnhanced/Configuration/configPage.html
@@ -43,7 +43,8 @@
Main Plugin Settings
Enable or disable the entire plugin functionality.
@@ -57,21 +58,25 @@
Show trailers as background if available. Adds a
mute/unmute and pause/play button to control the video in the right top corner.
-
+
-
If enabled, local trailers will be preferred over remote (YouTube) trailers.
+
If enabled, local trailers will be preferred over remote
+ (YouTube) trailers.
-
+
-
If enabled, local backdrop videos (Theme Videos) will be preferred over remote and local trailers.
+
If enabled, local backdrop videos (Theme Videos) will be
+ preferred over remote and local trailers.
If enabled, the slideshow will show the items listed
- below as the default content. If the list is empty, random items from your library are used.
+ below as the default content. If the list is empty, random items from your library are
+ used.
-
If enabled, the Max Items limit (Advanced → Content Limits) will also apply to Custom Media IDs and Collections. By default, custom lists are not limited.
+
If enabled, the Max Items limit (Advanced → Content
+ Limits) will also apply to Custom Media IDs and Collections. By default, custom lists
+ are not limited.
When enabled, seasonal sections below will override the default list or random selection
- during their active date ranges. If no season matches the current date, the default Custom Media IDs above or random selection are used as fallback.
+
When enabled, seasonal sections below will override the
+ default list or random selection
+ during their active date ranges. If no season matches the current date, the default
+ Custom Media IDs above or random selection are used as fallback.
-
+
info
-
Define seasonal rules to automatically select a selection of items based on the date. Rules are evaluated from top to bottom. The first matching rule wins.
+
Define seasonal rules to automatically select a selection of items based on the
+ date. Rules are evaluated from top to bottom. The first matching rule wins.
Enable the zooming-in effect on background images when a new slide is
- shown (does not affect trailer backdrops). Attention: This may cause performance issues on weaker client hardware.
+
Enable the zooming-in effect on background images when a new
+ slide is shown (does not affect trailer backdrops). Attention: This may cause
+ performance issues on weaker client hardware.
If enabled, users will see a media bar icon in the header to
- override settings (like disabling the bar or trailer backdrops) locally on their device.
+ override settings (like disabling the bar or trailer backdrops) locally on their device.
+
-
If enabled, a random video from the backdrops/theme videos will be selected instead of the first one (if multiple exist).
+
If enabled, a random video from the backdrops/theme videos
+ will be selected instead of the first one (if multiple exist).
-
If enabled, a random local trailer will be selected instead of the first one (if multiple exist).
+
If enabled, a random local trailer will be selected instead of
+ the first one (if multiple exist).
-
Skip intro/outro segments in YouTube trailers (if data is available).
+
Skip intro/outro segments in YouTube trailers (if data is
+ available).
-
+
+
+
+ Show Pagination Dots
+
+
Show or hide the pagination dots/counter navigation at the
+ bottom of the slideshow.
+
Max Pagination
Dots
@@ -397,7 +442,8 @@
name="IncludeWatchedContent" />
Include Watched Content
-
If enabled, watched content will be included in the random selection results.
+
If enabled, watched content will be included in the random
+ selection results.
@@ -459,7 +505,7 @@
'EnableSeasonalContent', 'EnableClientSideSettings', 'SortBy', 'SortOrder',
'PreferLocalTrailers', 'ApplyLimitsToCustomIds', 'SeasonalSections',
'PreferLocalBackdrops', 'RandomizeThemeVideos', 'RandomizeLocalTrailers',
- 'IncludeWatchedContent'
+ 'IncludeWatchedContent', 'ShowPaginationDots'
];
// Manual mapping for MediaBarIsEnabled -> IsEnabled, to avoid conflicts with other plugins
@@ -501,16 +547,16 @@
seasonalCheckbox.addEventListener('change', updateSeasonalVisibility);
updateSeasonalVisibility();
}
-
+
// Add Season Button
var addSeasonBtn = page.querySelector('#addSeasonBtn');
if (addSeasonBtn) {
// Remove existing listeners to avoid duplicates if re-attached
- var newBtn = addSeasonBtn.cloneNode(true);
- addSeasonBtn.parentNode.replaceChild(newBtn, addSeasonBtn);
- newBtn.addEventListener('click', function() {
- MediaBarEnhancedConfigurationPage.addSeasonalSection(page);
- });
+ var newBtn = addSeasonBtn.cloneNode(true);
+ addSeasonBtn.parentNode.replaceChild(newBtn, addSeasonBtn);
+ newBtn.addEventListener('click', function () {
+ MediaBarEnhancedConfigurationPage.addSeasonalSection(page);
+ });
}
// Handle Prefer Local Trailers visibility
@@ -545,7 +591,7 @@
if (seasonalInput) seasonalInput.value = sectionsJson;
var config = {};
-
+
// Manual mapping for MediaBarIsEnabled -> IsEnabled, to avoid conflicts with other plugins
var mediaBarEnabledCheckbox = page.querySelector('#MediaBarIsEnabled');
if (mediaBarEnabledCheckbox) {
@@ -563,7 +609,7 @@
'EnableSeasonalContent', 'EnableClientSideSettings', 'SortBy', 'SortOrder',
'PreferLocalTrailers', 'ApplyLimitsToCustomIds', 'SeasonalSections',
'PreferLocalBackdrops', 'RandomizeThemeVideos', 'RandomizeLocalTrailers',
- 'IncludeWatchedContent'
+ 'IncludeWatchedContent', 'ShowPaginationDots'
];
keys.forEach(function (key) {
@@ -582,16 +628,16 @@
});
},
- renderSeasonalSections: function(page, sections) {
+ renderSeasonalSections: function (page, sections) {
var container = page.querySelector('#seasonalSectionsList');
if (!container) return;
container.innerHTML = '';
- sections.forEach(function(section, index) {
+ sections.forEach(function (section, index) {
MediaBarEnhancedConfigurationPage.createSectionElement(container, section, index + 1);
});
},
- addSeasonalSection: function(page) {
+ addSeasonalSection: function (page) {
var container = page.querySelector('#seasonalSectionsList');
if (!container) return;
var index = container.children.length + 1;
@@ -603,25 +649,25 @@
}, index);
},
- createSectionElement: function(container, data, index) {
+ createSectionElement: function (container, data, index) {
var div = document.createElement('div');
div.className = 'seasonal-section';
div.style.cssText = 'background: rgba(0,0,0,0.2); padding: 1em; margin-bottom: 1em; border-radius: 4px; border: 1px solid rgba(255,255,255,0.1);';
-
+
var days = [];
- for(var i=1; i<=31; i++) days.push(i);
+ for (var i = 1; i <= 31; i++) days.push(i);
var months = [
- {v:1, n:'Jan'}, {v:2, n:'Feb'}, {v:3, n:'Mar'}, {v:4, n:'Apr'},
- {v:5, n:'May'}, {v:6, n:'Jun'}, {v:7, n:'Jul'}, {v:8, n:'Aug'},
- {v:9, n:'Sep'}, {v:10, n:'Oct'}, {v:11, n:'Nov'}, {v:12, n:'Dec'}
+ { v: 1, n: 'Jan' }, { v: 2, n: 'Feb' }, { v: 3, n: 'Mar' }, { v: 4, n: 'Apr' },
+ { v: 5, n: 'May' }, { v: 6, n: 'Jun' }, { v: 7, n: 'Jul' }, { v: 8, n: 'Aug' },
+ { v: 9, n: 'Sep' }, { v: 10, n: 'Oct' }, { v: 11, n: 'Nov' }, { v: 12, n: 'Dec' }
];
function mkSelect(val, opts, cls) {
var h = '';
- opts.forEach(function(o) {
+ opts.forEach(function (o) {
var v = o.v || o;
var n = o.n || o;
- h += '';
+ h += '';
});
h += '';
return h;
@@ -648,11 +694,11 @@
' Active Period' +
'
Date range (inclusive) when this content is active.
' +
'' +
@@ -662,19 +708,19 @@
'
Comma-separated or Newline separated list of Movie/Series/Collection IDs to show during this season. Same options available as for the default media IDs.
' +
'';
- div.querySelector('.btn-remove').addEventListener('click', function() {
+ div.querySelector('.btn-remove').addEventListener('click', function () {
div.remove();
MediaBarEnhancedConfigurationPage.updateSectionTitles(container);
});
- div.querySelector('.btn-move-up').addEventListener('click', function() {
+ div.querySelector('.btn-move-up').addEventListener('click', function () {
if (div.previousElementSibling) {
container.insertBefore(div, div.previousElementSibling);
MediaBarEnhancedConfigurationPage.updateSectionTitles(container);
}
});
- div.querySelector('.btn-move-down').addEventListener('click', function() {
+ div.querySelector('.btn-move-down').addEventListener('click', function () {
if (div.nextElementSibling) {
container.insertBefore(div.nextElementSibling, div);
MediaBarEnhancedConfigurationPage.updateSectionTitles(container);
@@ -684,9 +730,9 @@
container.appendChild(div);
},
- updateSectionTitles: function(container) {
+ updateSectionTitles: function (container) {
var sections = container.querySelectorAll('.seasonal-section');
- sections.forEach(function(section, index) {
+ sections.forEach(function (section, index) {
var title = section.querySelector('.section-title');
if (title) {
title.innerText = 'Season list #' + (index + 1);
@@ -694,10 +740,10 @@
});
},
- getSeasonalSectionsFromUI: function(page) {
+ getSeasonalSectionsFromUI: function (page) {
var sections = [];
var els = page.querySelectorAll('.seasonal-section');
- els.forEach(function(el) {
+ els.forEach(function (el) {
sections.push({
Name: el.querySelector('.section-name').value,
StartDay: parseInt(el.querySelector('.start-day').value),
diff --git a/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js b/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js
index 1b25b61..363a4f1 100644
--- a/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js
+++ b/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js
@@ -38,6 +38,7 @@ const CONFIG = {
preloadCount: 3,
fadeTransitionDuration: 500,
maxPaginationDots: 15,
+ showPaginationDots: true,
slideAnimationEnabled: true,
enableVideoBackdrop: true,
useSponsorBlock: true,
@@ -2280,6 +2281,8 @@ const SlideCreator = {
const SlideshowManager = {
createPaginationDots() {
+ if (!CONFIG.showPaginationDots) return;
+
let dotsContainer = document.querySelector(".dots-container");
if (!dotsContainer) {
dotsContainer = document.createElement("div");