Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8327fc5c9 | ||
|
|
9ffe03f0df | ||
|
|
37e99d7fed | ||
|
|
9b0e3762ac | ||
|
|
48f93e3480 | ||
|
|
2e9c093cdc | ||
|
|
60593dc855 | ||
|
|
0edde43720 | ||
|
|
0f6938a91d | ||
|
|
fe661925e0 | ||
|
|
5fbe60c27a | ||
|
|
89bde9233d | ||
|
|
24ac119e01 | ||
|
|
1ee4aaefb5 | ||
|
|
d737bc9422 | ||
|
|
2a154aaf92 | ||
|
|
561a4254b2 | ||
|
|
b8a0c7f589 | ||
|
|
10e02eeb3c | ||
|
|
f39200544d | ||
|
|
5173f66449 | ||
|
|
965942f63b | ||
|
|
c251cf7e70 | ||
|
|
8699e0b3e2 | ||
|
|
5db2157232 | ||
|
|
822f572006 | ||
|
|
e6637b34f7 | ||
|
|
1acaff6552 | ||
|
|
58188ca094 | ||
|
|
37b30aef1a | ||
|
|
f0370ac57f | ||
|
|
0663b7d9e4 | ||
|
|
e3213f72cc | ||
|
|
6c131aef58 | ||
|
|
0747f63d11 |
@@ -120,11 +120,14 @@ jobs:
|
||||
run: |
|
||||
cd central-manifest
|
||||
|
||||
REPO_OWNER="${{ github.repository_owner }}"
|
||||
REPO_NAME="${{ github.event.repository.name }}"
|
||||
|
||||
# 1. Get info from previous steps
|
||||
VERSION="${{ env.VERSION }}"
|
||||
HASH="${{ env.ZIP_HASH }}"
|
||||
TIME="${{ env.BUILD_TIME }}"
|
||||
DOWNLOAD_URL="https://git.mahom03-spacecloud.de/${{ github.repository }}/releases/download/v$VERSION/Jellyfin.Plugin.MediaBarEnhanced.zip"
|
||||
DOWNLOAD_URL="https://git.mahom03-spacecloud.de/$REPO_OWNER/$REPO_NAME/releases/download/v$VERSION/Jellyfin.Plugin.MediaBarEnhanced.zip"
|
||||
|
||||
# 2. Get info from env
|
||||
PLUGIN_GUID="${{ env.PLUGIN_GUID }}"
|
||||
@@ -186,20 +189,23 @@ jobs:
|
||||
- name: Checkout Seasonal Manifest Repo
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: ${{ github.repository_owner }}/jellyfin-plugin-manifest
|
||||
repository: ${{ github.repository_owner }}/Jellyfin-Seasonals-Plugin
|
||||
path: seasonal-manifest
|
||||
token: ${{ secrets.JELLYFIN_PLUGIN_MANIFEST_UPDATER_PAT }}
|
||||
|
||||
- name: Update Central Manifest
|
||||
- name: Update Seasonal Manifest
|
||||
shell: bash
|
||||
run: |
|
||||
cd seasonal-manifest
|
||||
|
||||
REPO_OWNER="${{ github.repository_owner }}"
|
||||
REPO_NAME="${{ github.event.repository.name }}"
|
||||
|
||||
# 1. Get info from previous steps
|
||||
VERSION="${{ env.VERSION }}"
|
||||
HASH="${{ env.ZIP_HASH }}"
|
||||
TIME="${{ env.BUILD_TIME }}"
|
||||
DOWNLOAD_URL="https://git.mahom03-spacecloud.de/${{ github.repository }}/releases/download/v$VERSION/Jellyfin.Plugin.MediaBarEnhanced.zip"
|
||||
DOWNLOAD_URL="https://git.mahom03-spacecloud.de/$REPO_OWNER/$REPO_NAME/releases/download/v$VERSION/Jellyfin.Plugin.MediaBarEnhanced.zip"
|
||||
|
||||
# 2. Get info from env
|
||||
PLUGIN_GUID="${{ env.PLUGIN_GUID }}"
|
||||
|
||||
12
.github/workflows/release_automation.yml
vendored
12
.github/workflows/release_automation.yml
vendored
@@ -99,7 +99,7 @@ jobs:
|
||||
with:
|
||||
tag_name: "v${{ env.VERSION }}"
|
||||
name: "v${{ env.VERSION }}"
|
||||
# body: ${{ env.CHANGELOG }}
|
||||
body: ${{ env.CHANGELOG }}
|
||||
files: ${{ env.ZIP_PATH }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
@@ -118,6 +118,9 @@ jobs:
|
||||
run: |
|
||||
cd central-manifest
|
||||
|
||||
REPO_OWNER="${{ github.repository_owner }}"
|
||||
REPO_NAME="${{ github.event.repository.name }}"
|
||||
|
||||
# 1. Get info from previous steps
|
||||
VERSION="${{ env.VERSION }}"
|
||||
HASH="${{ env.ZIP_HASH }}"
|
||||
@@ -184,15 +187,18 @@ jobs:
|
||||
- name: Checkout Seasonal Manifest Repo
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: ${{ github.repository_owner }}/jellyfin-plugin-manifest
|
||||
repository: ${{ github.repository_owner }}/Jellyfin-Seasonals
|
||||
path: seasonal-manifest
|
||||
token: ${{ secrets.JELLYFIN_PLUGIN_MANIFEST_UPDATER_PAT }}
|
||||
|
||||
- name: Update Central Manifest
|
||||
- name: Update Seasonal Manifest
|
||||
shell: bash
|
||||
run: |
|
||||
cd seasonal-manifest
|
||||
|
||||
REPO_OWNER="${{ github.repository_owner }}"
|
||||
REPO_NAME="${{ github.event.repository.name }}"
|
||||
|
||||
# 1. Get info from previous steps
|
||||
VERSION="${{ env.VERSION }}"
|
||||
HASH="${{ env.ZIP_HASH }}"
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,7 +4,5 @@ obj/
|
||||
.idea/
|
||||
artifacts
|
||||
|
||||
example-plugins/
|
||||
|
||||
*.md
|
||||
!README.md
|
||||
@@ -30,7 +30,8 @@ namespace Jellyfin.Plugin.MediaBarEnhanced.Configuration
|
||||
public bool EnableKeyboardControls { get; set; } = true;
|
||||
public bool AlwaysShowArrows { get; set; } = false;
|
||||
public string CustomMediaIds { get; set; } = "";
|
||||
public bool EnableCustomMediaIds { get; set; } = false;
|
||||
public bool EnableCustomMediaIds { get; set; } = true;
|
||||
public string PreferredVideoQuality { get; set; } = "Auto";
|
||||
public bool EnableSeasonalContent { get; set; } = false;
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
}
|
||||
|
||||
@@ -93,8 +93,9 @@
|
||||
name="EnableCustomMediaIds" />
|
||||
<span>Enable Custom Media IDs</span>
|
||||
</label>
|
||||
<div class="fieldDescription">If enabled, the slideshow will ONLY show the items listed
|
||||
below.</div>
|
||||
<div class="fieldDescription">If enabled, the slideshow will try to show the items listed
|
||||
below. If the list is empty, default behavior (random items) is used. Disable this
|
||||
to temporarily ignore your custom list without deleting it.</div>
|
||||
</div>
|
||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||
<label>
|
||||
@@ -113,7 +114,10 @@
|
||||
style="width: 100%; height: 150px; font-family: monospace;"></textarea>
|
||||
<div class="fieldDescription" id="customMediaIdsDesc">Enter the IDs of the items you want to
|
||||
show in the slideshow.
|
||||
You can separate them by comma or new line.</div>
|
||||
You can separate them by comma or new line.
|
||||
You can also add a description after the ID using any separator like space, pipe
|
||||
(|) or dash (-) (e.g. <code>ID | Description</code>).
|
||||
Note: The separator MUST NOT be a hex character (0-9, a-f).</div>
|
||||
<div class="fieldDescription" id="seasonalMediaIdsDesc" style="display: none;">
|
||||
<b>Seasonal Mode Enabled:</b> Define lines with date ranges (Format: DD.MM-DD.MM |
|
||||
<i>name</i> | <i>IDs</i>).<br>
|
||||
@@ -125,11 +129,10 @@
|
||||
</div>
|
||||
<p>You can find the IDs of your items in the URL of the item page in the web interface.<br>
|
||||
Example:
|
||||
<code>https://your-jellyfin-url/web/#/details?id=<b style="color:red;">your-item-id</b>&serverId=your-server-id</code><br>
|
||||
<code>https://your-jellyfin-url/web/#/details?id=<b style="color:red;">your-item-id</b>&serverId=your-server-id</code><br><br>
|
||||
You can also insert a name of a collection or playlist to fetch the IDs of all items in
|
||||
it (will take the first hit. Note: there is currently no feedback if the name resolution
|
||||
succeeded, you
|
||||
will have to look if the bar displays the correct items.).
|
||||
it (will take the first hit.<br>Note: there is currently no feedback if the name
|
||||
resolution succeeded, you will have to look if the bar displays the correct items.).
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -153,6 +156,18 @@
|
||||
</label>
|
||||
<div class="fieldDescription">Skip intro/outro segments in YouTube trailers.</div>
|
||||
</div>
|
||||
<div class="selectContainer">
|
||||
<label class="selectLabel" for="PreferredVideoQuality">Preferred YouTube Quality</label>
|
||||
<select is="emby-select" id="PreferredVideoQuality" name="PreferredVideoQuality"
|
||||
class="emby-select-withcolor emby-select">
|
||||
<option value="Auto">Auto (Smart)</option>
|
||||
<option value="Maximum">Maximum (4K+)</option>
|
||||
<option value="1080p">1080p</option>
|
||||
<option value="720p">720p</option>
|
||||
</select>
|
||||
<div class="fieldDescription">"Auto" selects Maximum if screen width > 1920px, otherwise
|
||||
1080p.</div>
|
||||
</div>
|
||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||
<label>
|
||||
<input is="emby-checkbox" type="checkbox" id="StartMuted" name="StartMuted" />
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<!-- <TreatWarningsAsErrors>false</TreatWarningsAsErrors> -->
|
||||
<Title>Jellyfin Media Bar Enhanced Plugin</Title>
|
||||
<Authors>CodeDevMLH</Authors>
|
||||
<Version>1.0.0.2</Version>
|
||||
<Version>1.2.0.0</Version>
|
||||
<RepositoryUrl>https://github.com/CodeDevMLH/jellyfin-plugin-media-bar-enhanced</RepositoryUrl>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ using Microsoft.Extensions.Logging;
|
||||
namespace Jellyfin.Plugin.MediaBarEnhanced
|
||||
{
|
||||
/// <summary>
|
||||
/// The main plugin.
|
||||
/// The main plugin.
|
||||
/// </summary>
|
||||
public class MediaBarEnhancedPlugin : BasePlugin<PluginConfiguration>, IHasWebPages
|
||||
{
|
||||
|
||||
@@ -18,10 +18,8 @@ namespace Jellyfin.Plugin.MediaBarEnhanced
|
||||
{
|
||||
private readonly IApplicationPaths _appPaths;
|
||||
private readonly ILogger<ScriptInjector> _logger;
|
||||
public const string ScriptTag = "<script src=\"/MediaBarEnhanced/Resources/slideshowpure.js\" defer></script>";
|
||||
public const string CssTag = "<link rel=\"stylesheet\" href=\"/MediaBarEnhanced/Resources/slideshowpure.css\" />";
|
||||
// private const string ScriptTag = "<script src=\"/MediaBarEnhanced/Resources/media-bar.js\" defer></script>";
|
||||
// private const string CssTag = "<link rel=\"stylesheet\" href=\"/MediaBarEnhanced/Resources/media-bar.css\">";
|
||||
public const string ScriptTag = "<script src=\"/MediaBarEnhanced/Resources/mediaBarEnhanced.js\" defer></script>";
|
||||
public const string CssTag = "<link rel=\"stylesheet\" href=\"/MediaBarEnhanced/Resources/mediaBarEnhanced.css\" />";
|
||||
public const string ScriptMarker = "</body>";
|
||||
public const string CssMarker = "</head>";
|
||||
|
||||
@@ -39,7 +37,6 @@ namespace Jellyfin.Plugin.MediaBarEnhanced
|
||||
/// <summary>
|
||||
/// Injects the script tag into index.html if it's not already present.
|
||||
/// </summary>
|
||||
/// <returns>True if injection was successful or already present, false otherwise.</returns>
|
||||
public void Inject()
|
||||
{
|
||||
try
|
||||
@@ -103,6 +100,11 @@ namespace Jellyfin.Plugin.MediaBarEnhanced
|
||||
_logger.LogInformation("MediaBarEnhanced script and CSS already present in index.html. Or could not be injected.");
|
||||
}
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
_logger.LogWarning("Unauthorized access when attempting to inject script into index.html. Automatic injection failed. Attempting fallback now...");
|
||||
RegisterFileTransformation();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error injecting MediaBarEnhanced resources. Attempting fallback.");
|
||||
@@ -150,8 +152,15 @@ namespace Jellyfin.Plugin.MediaBarEnhanced
|
||||
{
|
||||
File.WriteAllText(indexPath, content);
|
||||
_logger.LogInformation("MediaBarEnhanced script removed from index.html.");
|
||||
} else
|
||||
{
|
||||
_logger.LogInformation("MediaBarEnhanced script not found in index.html. No removal necessary.");
|
||||
}
|
||||
}
|
||||
catch (UnauthorizedAccessException uaEx)
|
||||
{
|
||||
_logger.LogError(uaEx, "Unauthorized access when trying to remove MediaBarEnhanced script. Check file permissions.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error removing MediaBarEnhanced script.");
|
||||
@@ -172,7 +181,6 @@ namespace Jellyfin.Plugin.MediaBarEnhanced
|
||||
|
||||
{
|
||||
JObject payload = new JObject();
|
||||
// Random GUID for ID
|
||||
payload.Add("id", "0dfac9d7-d898-4944-900b-1c1837707279");
|
||||
payload.Add("fileNamePattern", "index.html");
|
||||
payload.Add("callbackAssembly", GetType().Assembly.FullName);
|
||||
@@ -223,7 +231,6 @@ namespace Jellyfin.Plugin.MediaBarEnhanced
|
||||
|
||||
if (pluginInterfaceType != null)
|
||||
{
|
||||
// The ID must match the one used in RegisterFileTransformation
|
||||
Guid id = Guid.Parse("0dfac9d7-d898-4944-900b-1c1837707279");
|
||||
pluginInterfaceType.GetMethod("RemoveTransformation")?.Invoke(null, new object?[] { id });
|
||||
_logger.LogInformation("File transformation unregistered successfully.");
|
||||
@@ -232,7 +239,6 @@ namespace Jellyfin.Plugin.MediaBarEnhanced
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log but don't throw, as we want to continue with normal removal
|
||||
_logger.LogWarning(ex, "Error attempting to unregister file transformation. It might not have been registered.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,9 +42,10 @@ const CONFIG = {
|
||||
fullWidthVideo: true,
|
||||
enableMobileVideo: false,
|
||||
showTrailerButton: true,
|
||||
preferredVideoQuality: "Auto",
|
||||
enableKeyboardControls: true,
|
||||
alwaysShowArrows: false,
|
||||
enableCustomMediaIds: false,
|
||||
enableCustomMediaIds: true,
|
||||
enableSeasonalContent: false,
|
||||
customMediaIds: "",
|
||||
enableLoadingScreen: true,
|
||||
@@ -1259,11 +1260,13 @@ const VisibilityObserver = {
|
||||
if (isVisible) {
|
||||
if (STATE.slideshow.slideInterval && !STATE.slideshow.isPaused) {
|
||||
STATE.slideshow.slideInterval.start();
|
||||
SlideshowManager.resumeActivePlayback();
|
||||
}
|
||||
} else {
|
||||
if (STATE.slideshow.slideInterval) {
|
||||
STATE.slideshow.slideInterval.stop();
|
||||
}
|
||||
SlideshowManager.stopAllPlayback();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1415,6 +1418,21 @@ const SlideCreator = {
|
||||
loop: 0
|
||||
};
|
||||
|
||||
// Determine video quality
|
||||
let quality = 'hd1080';
|
||||
if (CONFIG.preferredVideoQuality === 'Maximum') {
|
||||
quality = 'highres';
|
||||
} else if (CONFIG.preferredVideoQuality === '720p') {
|
||||
quality = 'hd720';
|
||||
} else if (CONFIG.preferredVideoQuality === '1080p') {
|
||||
quality = 'hd1080';
|
||||
} else { // Auto or fallback
|
||||
// If screen is wider than 1920, prefer highres, otherwise 1080p
|
||||
quality = window.screen.width > 1920 ? 'highres' : 'hd1080';
|
||||
}
|
||||
|
||||
playerVars.suggestedQuality = quality;
|
||||
|
||||
// Apply SponsorBlock start/end times
|
||||
if (segments.intro) {
|
||||
playerVars.start = Math.ceil(segments.intro[1]);
|
||||
@@ -1444,6 +1462,10 @@ const SlideCreator = {
|
||||
event.target.setVolume(40);
|
||||
}
|
||||
|
||||
if (typeof event.target.setPlaybackQuality === 'function') {
|
||||
event.target.setPlaybackQuality(quality);
|
||||
}
|
||||
|
||||
// Only play if this is the active slide
|
||||
const slide = document.querySelector(`.slide[data-item-id="${itemId}"]`);
|
||||
if (slide && slide.classList.contains('active')) {
|
||||
@@ -1492,6 +1514,7 @@ const SlideCreator = {
|
||||
className: "backdrop video-backdrop",
|
||||
src: trailerUrl,
|
||||
autoplay: false,
|
||||
preload: "auto",
|
||||
loop: false,
|
||||
style: "object-fit: cover; width: 100%; height: 100%; pointer-events: none;"
|
||||
};
|
||||
@@ -2317,6 +2340,65 @@ const SlideshowManager = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Stops all video playback (YouTube and HTML5)
|
||||
* Used when navigating away from the home screen
|
||||
*/
|
||||
stopAllPlayback() {
|
||||
// 1. Pause all YouTube players
|
||||
if (STATE.slideshow.videoPlayers) {
|
||||
Object.values(STATE.slideshow.videoPlayers).forEach(player => {
|
||||
try {
|
||||
if (player && typeof player.pauseVideo === 'function') {
|
||||
player.pauseVideo();
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("Error pausing YouTube player:", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 2. Pause all HTML5 videos
|
||||
const container = document.getElementById("slides-container");
|
||||
if (container) {
|
||||
container.querySelectorAll('video').forEach(video => {
|
||||
try {
|
||||
video.pause();
|
||||
} catch (e) {
|
||||
console.warn("Error pausing HTML5 video:", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Resumes playback for the active slide if not globally paused
|
||||
*/
|
||||
resumeActivePlayback() {
|
||||
if (STATE.slideshow.isPaused) return;
|
||||
|
||||
const currentItemId = STATE.slideshow.itemIds[STATE.slideshow.currentSlideIndex];
|
||||
if (!currentItemId) return;
|
||||
|
||||
const currentSlide = document.querySelector(`.slide[data-item-id="${currentItemId}"]`);
|
||||
if (!currentSlide) return;
|
||||
|
||||
// 1. Try YouTube Player
|
||||
const ytPlayer = STATE.slideshow.videoPlayers[currentItemId];
|
||||
if (ytPlayer && typeof ytPlayer.playVideo === 'function') {
|
||||
ytPlayer.playVideo();
|
||||
}
|
||||
|
||||
// 2. Try HTML5 Video
|
||||
const html5Video = currentSlide.querySelector('video');
|
||||
if (html5Video) {
|
||||
if (STATE.slideshow.isMuted) {
|
||||
html5Video.muted = true;
|
||||
}
|
||||
html5Video.play().catch(e => console.warn("Error resuming HTML5 video:", e));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes touch events for swiping
|
||||
*/
|
||||
@@ -2514,17 +2596,23 @@ const SlideshowManager = {
|
||||
try {
|
||||
let id = rawId;
|
||||
|
||||
// If not a valid GUID, treat as a name and search
|
||||
// If not a valid GUID, check if it starts with one (comments) or treat as a name
|
||||
if (!guidRegex.test(rawId)) {
|
||||
console.log(`Input '${rawId}' is not a GUID, searching for Collection/Playlist by name...`);
|
||||
const resolvedId = await ApiUtils.findCollectionOrPlaylistByName(rawId);
|
||||
const guidMatch = rawId.match(/^([0-9a-f]{32})(?:[^0-9a-f]|$)/i);
|
||||
|
||||
if (resolvedId) {
|
||||
console.log(`Resolved name '${rawId}' to ID: ${resolvedId}`);
|
||||
id = resolvedId;
|
||||
if (guidMatch) {
|
||||
id = guidMatch[1];
|
||||
} else {
|
||||
console.warn(`Could not find Collection or Playlist with name: '${rawId}'`);
|
||||
continue; // Skip if resolution failed
|
||||
console.log(`Input '${rawId}' is not a GUID, searching for Collection/Playlist by name...`);
|
||||
const resolvedId = await ApiUtils.findCollectionOrPlaylistByName(rawId);
|
||||
|
||||
if (resolvedId) {
|
||||
console.log(`Resolved name '${rawId}' to ID: ${resolvedId}`);
|
||||
id = resolvedId;
|
||||
} else {
|
||||
console.warn(`Could not find Collection or Playlist with name: '${rawId}'`);
|
||||
continue; // Skip if resolution failed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2839,7 +2927,7 @@ const slidesInit = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
window.slideshowPure = {
|
||||
window.mediaBarEnhanced = {
|
||||
CONFIG,
|
||||
STATE,
|
||||
SlideUtils,
|
||||
44
README.md
44
README.md
@@ -2,7 +2,7 @@
|
||||
|
||||
Media Bar Enhanced is a plugin for Jellyfin that introduces a customizable and interactive media bar to your dashboard view on Jellyfin web.
|
||||
|
||||
This plugin is a fork and enhancement of the original [Media Bar by MakD](https://github.com/MakD/Jellyfin-Media-Bar) media bar, but can be installed as plugin for easier installation and management/configuration.
|
||||
This plugin is a fork and enhancement of the original [Media Bar by MakD](https://github.com/MakD/Jellyfin-Media-Bar), but can be installed as plugin for easier installation and management/configuration.
|
||||
|
||||

|
||||
|
||||
@@ -11,6 +11,7 @@ This plugin is a fork and enhancement of the original [Media Bar by MakD](https:
|
||||
## Table of Contents
|
||||
- [Jellyfin Media Bar Enhanced Plugin](#jellyfin-media-bar-enhanced-plugin)
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [Overview](#overview)
|
||||
- [Features](#features)
|
||||
- [New Features \& Enhancements](#new-features--enhancements)
|
||||
- [Core Features](#core-features)
|
||||
@@ -28,6 +29,45 @@ This plugin is a fork and enhancement of the original [Media Bar by MakD](https:
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||

|
||||
|
||||
Expand to get more impressions:
|
||||
|
||||
<details>
|
||||
<summary>Desktop Layout</summary>
|
||||
|
||||
<img width="1920" height="1080" alt="trailer button" src="https://github.com/user-attachments/assets/5dce8eb1-8f2f-4583-a6d5-16f27ced8608" />
|
||||
Normal mode like the original with additional trailer button
|
||||
<br><br><br>
|
||||
|
||||
<img width="1920" height="993" alt="modal_desktop" src="https://github.com/user-attachments/assets/9087f43d-cd9d-4581-a7e0-404b75bc8e02" />
|
||||
Trailer modal
|
||||
<br><br><br>
|
||||
|
||||
<img width="1920" height="994" alt="config" src="https://github.com/user-attachments/assets/5492c384-a5c4-47ee-9428-3d9de2748e63" />
|
||||
Excerpt from the config: E.g. here you can simply add your items that should be displayed
|
||||
<br><br>
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Mobile Layout</summary>
|
||||
|
||||

|
||||
<br>If trailer on mobile is eenabled...
|
||||
<br><br><br>
|
||||
|
||||
<img width="1080" height="2199" alt="mobile" src="https://github.com/user-attachments/assets/f0a0cc0d-f019-45f5-96c8-a5de14bf92ba" />
|
||||
Normal mode like the original with additional trailer button
|
||||
<br><br><br>
|
||||
|
||||
<img width="1080" height="2199" alt="trailer_modal_mobile" src="https://github.com/user-attachments/assets/944f9b82-9c9b-411f-883b-877b65ed933f" />
|
||||
Trailer modal in portrait mode
|
||||
<br><br>
|
||||
</details>
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
This plugin builds upon the original Media Bar with new capabilities and improvements:
|
||||
@@ -192,4 +232,4 @@ volumes:
|
||||
|
||||
## Contributing
|
||||
|
||||
Feel free to contribute to this project by creating pull requests or reporting issues.
|
||||
Feel free to contribute to this project by creating pull requests or reporting issues.
|
||||
|
||||
@@ -9,20 +9,36 @@
|
||||
"imageUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/raw/branch/main/logo.png",
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.0.0.2",
|
||||
"changelog": "fixes",
|
||||
"version": "1.2.0.0",
|
||||
"changelog": "- Add video quality preference setting (Auto / 1080p / Highres)\n- Set preferred video quality on YouTube player based on setting",
|
||||
"targetAbi": "10.11.0.0",
|
||||
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/releases/download/v1.0.0.2/Jellyfin.Plugin.MediaBarEnhanced.zip",
|
||||
"checksum": "1041b403ec0193c2172a6fe15501afd3",
|
||||
"timestamp": "2026-01-06T21:21:37Z"
|
||||
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/releases/download/v1.2.0.0/Jellyfin.Plugin.MediaBarEnhanced.zip",
|
||||
"checksum": "2f1628d864b35cb710431974a8b85bee",
|
||||
"timestamp": "2026-01-08T22:16:05Z"
|
||||
},
|
||||
{
|
||||
"version": "1.0.0.1",
|
||||
"changelog": "fixes",
|
||||
"version": "1.1.2.0",
|
||||
"changelog": "- Add method to resume video playback when slideshow is active",
|
||||
"targetAbi": "10.11.0.0",
|
||||
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/releases/download/v1.0.0.1/Jellyfin.Plugin.MediaBarEnhanced.zip",
|
||||
"checksum": "f4e6194a9cc72fdda7436161c73832de",
|
||||
"timestamp": "2026-01-06T21:18:33Z"
|
||||
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/releases/download/v1.1.2.0/Jellyfin.Plugin.MediaBarEnhanced.zip",
|
||||
"checksum": "a0e8ff5e59b22a1bdedc916cd5e1c16a",
|
||||
"timestamp": "2026-01-08T15:26:55Z"
|
||||
},
|
||||
{
|
||||
"version": "1.1.1.0",
|
||||
"changelog": "- Add method to pause all video playback when navigating away from home screen",
|
||||
"targetAbi": "10.11.0.0",
|
||||
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/releases/download/v1.1.1.0/Jellyfin.Plugin.MediaBarEnhanced.zip",
|
||||
"checksum": "09da95fc561b11191d23a5cfa30ea731",
|
||||
"timestamp": "2026-01-08T14:54:57Z"
|
||||
},
|
||||
{
|
||||
"version": "1.1.0.0",
|
||||
"changelog": "- 'custom media IDs' setting is now enabled by default (no input --> random selection)\n- improve GUID handling in slideshow manager to handle seperator and description",
|
||||
"targetAbi": "10.11.0.0",
|
||||
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/releases/download/v1.1.0.0/Jellyfin.Plugin.MediaBarEnhanced.zip",
|
||||
"checksum": "32305d72b8d704acf8eef0c22277fee9",
|
||||
"timestamp": "2026-01-08T02:15:50Z"
|
||||
},
|
||||
{
|
||||
"version": "1.0.0.0",
|
||||
|
||||
Reference in New Issue
Block a user