Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f437a546d2 | ||
|
|
15520fdff8 | ||
|
|
3093e88ffb | ||
|
|
e4ba5130fa | ||
|
|
de57f1c20b | ||
|
|
a5e98bdd93 | ||
|
|
ed5c0ab696 | ||
|
|
ffcbd21eb6 | ||
|
|
4ddd83ba4d | ||
|
|
b08a93718e | ||
|
|
eecb81d59a | ||
|
|
664eecf779 | ||
|
|
c833a94c3f | ||
|
|
b1c39b4b38 | ||
|
|
5e398d06a8 | ||
|
|
23a73543c9 | ||
|
|
8804048c61 | ||
|
|
992f854dd2 |
@@ -49,6 +49,8 @@ namespace Jellyfin.Plugin.MediaBarEnhanced.Configuration
|
|||||||
public bool IncludeWatchedContent { get; set; } = false;
|
public bool IncludeWatchedContent { get; set; } = false;
|
||||||
public string SortBy { get; set; } = "Random";
|
public string SortBy { get; set; } = "Random";
|
||||||
public string SortOrder { get; set; } = "Ascending";
|
public string SortOrder { get; set; } = "Ascending";
|
||||||
|
public int BackdropVideoDelay { get; set; } = 0;
|
||||||
|
public bool ConstrainPlotWidth { get; set; } = false;
|
||||||
|
|
||||||
public bool EnableCustomOverlay { get; set; } = false;
|
public bool EnableCustomOverlay { get; set; } = false;
|
||||||
public string CustomOverlayText { get; set; } = "";
|
public string CustomOverlayText { get; set; } = "";
|
||||||
|
|||||||
@@ -418,6 +418,13 @@
|
|||||||
on
|
on
|
||||||
mobile devices. (looks bad on desktops)</div>
|
mobile devices. (looks bad on desktops)</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
|
<label>
|
||||||
|
<input is="emby-checkbox" type="checkbox" id="ConstrainPlotWidth" name="ConstrainPlotWidth" />
|
||||||
|
<span>Constrain Plot Width</span>
|
||||||
|
</label>
|
||||||
|
<div class="fieldDescription">Align the description text left to match the logo width, preventing it from crossing the entire screen. (Increases the text limit to 3 lines instead of 2).</div>
|
||||||
|
</div>
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
<label>
|
<label>
|
||||||
<input is="emby-checkbox" type="checkbox" id="EnableLoadingScreen"
|
<input is="emby-checkbox" type="checkbox" id="EnableLoadingScreen"
|
||||||
@@ -463,6 +470,11 @@
|
|||||||
<input is="emby-input" type="number" id="ShuffleInterval" name="ShuffleInterval" />
|
<input is="emby-input" type="number" id="ShuffleInterval" name="ShuffleInterval" />
|
||||||
<div class="fieldDescription">Time in milliseconds between changing slides.</div>
|
<div class="fieldDescription">Time in milliseconds between changing slides.</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="inputContainer">
|
||||||
|
<label class="inputLabel inputLabelUnfocused" for="BackdropVideoDelay">Backdrop Video Delay (ms)</label>
|
||||||
|
<input is="emby-input" type="number" id="BackdropVideoDelay" name="BackdropVideoDelay" />
|
||||||
|
<div class="fieldDescription">Time in milliseconds to wait before playing backdrops/theme videos (leaves static backdrop visible longer).</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="inputContainer">
|
<div class="inputContainer">
|
||||||
<label class="inputLabel inputLabelUnfocused" for="RetryInterval">Retry Interval
|
<label class="inputLabel inputLabelUnfocused" for="RetryInterval">Retry Interval
|
||||||
@@ -594,10 +606,10 @@
|
|||||||
enable counter style directly.</div>
|
enable counter style directly.</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="inputContainer">
|
<div class="inputContainer">
|
||||||
<label class="inputLabel inputLabelUnfocused" for="MaxPlotLength">Max Plot
|
<label class="inputLabel inputLabelUnfocused" for="MaxPlotLength">Max Plot Length</label>
|
||||||
Length</label>
|
|
||||||
<input is="emby-input" type="number" id="MaxPlotLength" name="MaxPlotLength" />
|
<input is="emby-input" type="number" id="MaxPlotLength" name="MaxPlotLength" />
|
||||||
<div class="fieldDescription">Maximum characters for the plot summary.</div>
|
<div class="fieldDescription">Maximum characters for the plot summary. Limited to max 2 lines
|
||||||
|
(or 3 if 'Constrain Plot Width' is enabled).</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -663,7 +675,8 @@
|
|||||||
'MaxDaysRecent', 'ExcludeSeasonalContent', 'HideArrowsOnMobile',
|
'MaxDaysRecent', 'ExcludeSeasonalContent', 'HideArrowsOnMobile',
|
||||||
'EnableCustomOverlay', 'CustomOverlayText', 'CustomOverlayImageUrl',
|
'EnableCustomOverlay', 'CustomOverlayText', 'CustomOverlayImageUrl',
|
||||||
'CustomOverlayStyle', 'CustomOverlayImageStyle', 'CustomOverlayPriority',
|
'CustomOverlayStyle', 'CustomOverlayImageStyle', 'CustomOverlayPriority',
|
||||||
'CustomOverlayPositionX', 'CustomOverlayPositionY', 'CustomOverlayScale'
|
'CustomOverlayPositionX', 'CustomOverlayPositionY', 'CustomOverlayScale',
|
||||||
|
'BackdropVideoDelay', 'ConstrainPlotWidth'
|
||||||
];
|
];
|
||||||
|
|
||||||
// Manual mapping for MediaBarIsEnabled -> IsEnabled, to avoid conflicts with other plugins
|
// Manual mapping for MediaBarIsEnabled -> IsEnabled, to avoid conflicts with other plugins
|
||||||
@@ -908,7 +921,8 @@
|
|||||||
'MaxDaysRecent', 'ExcludeSeasonalContent', 'HideArrowsOnMobile',
|
'MaxDaysRecent', 'ExcludeSeasonalContent', 'HideArrowsOnMobile',
|
||||||
'EnableCustomOverlay', 'CustomOverlayText', 'CustomOverlayImageUrl',
|
'EnableCustomOverlay', 'CustomOverlayText', 'CustomOverlayImageUrl',
|
||||||
'CustomOverlayStyle', 'CustomOverlayImageStyle', 'CustomOverlayPriority',
|
'CustomOverlayStyle', 'CustomOverlayImageStyle', 'CustomOverlayPriority',
|
||||||
'CustomOverlayPositionX', 'CustomOverlayPositionY', 'CustomOverlayScale'
|
'CustomOverlayPositionX', 'CustomOverlayPositionY', 'CustomOverlayScale',
|
||||||
|
'BackdropVideoDelay', 'ConstrainPlotWidth'
|
||||||
];
|
];
|
||||||
|
|
||||||
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.8.1.2</Version>
|
<Version>1.9.0.0</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>
|
||||||
|
|
||||||
|
|||||||
@@ -489,6 +489,15 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.plot-container.constrained-plot {
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plot-container.constrained-plot .plot {
|
||||||
|
line-clamp: 3;
|
||||||
|
-webkit-line-clamp: 3;
|
||||||
|
}
|
||||||
|
|
||||||
.genre {
|
.genre {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ const CONFIG = {
|
|||||||
customOverlayPositionX: 0,
|
customOverlayPositionX: 0,
|
||||||
customOverlayPositionY: 0,
|
customOverlayPositionY: 0,
|
||||||
customOverlayScale: 100,
|
customOverlayScale: 100,
|
||||||
|
backdropVideoDelay: 0,
|
||||||
|
constrainPlotWidth: false,
|
||||||
enableCustomMediaIds: true,
|
enableCustomMediaIds: true,
|
||||||
enableSeasonalContent: false,
|
enableSeasonalContent: false,
|
||||||
customMediaIds: "",
|
customMediaIds: "",
|
||||||
@@ -110,6 +112,7 @@ const STATE = {
|
|||||||
customTrailerUrls: {},
|
customTrailerUrls: {},
|
||||||
ytPromise: null,
|
ytPromise: null,
|
||||||
autoplayTimeouts: [],
|
autoplayTimeouts: [],
|
||||||
|
playSignals: {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -396,6 +399,7 @@ const resetSlideshowState = () => {
|
|||||||
STATE.slideshow.customTrailerUrls = {};
|
STATE.slideshow.customTrailerUrls = {};
|
||||||
STATE.slideshow.totalItems = 0;
|
STATE.slideshow.totalItems = 0;
|
||||||
STATE.slideshow.isLoading = false;
|
STATE.slideshow.isLoading = false;
|
||||||
|
STATE.slideshow.playSignals = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1802,7 +1806,7 @@ const SlideCreator = {
|
|||||||
// Create an iframe upfront
|
// Create an iframe upfront
|
||||||
const ytPlayerIframe = SlideUtils.createElement("iframe", {
|
const ytPlayerIframe = SlideUtils.createElement("iframe", {
|
||||||
id: `youtube-player-${itemId}`,
|
id: `youtube-player-${itemId}`,
|
||||||
src: `https://www.youtube-nocookie.com/embed/${videoId}?enablejsapi=1&origin=${encodeURIComponent(window.location.origin)}`,
|
src: `https://www.youtube-nocookie.com/embed/${videoId}?enablejsapi=1&autoplay=0&controls=0&playsinline=1&mute=${STATE.slideshow.isMuted ? 1 : 0}&origin=${encodeURIComponent(window.location.origin)}`,
|
||||||
style: "width: 100%; height: 100%; border: none;",
|
style: "width: 100%; height: 100%; border: none;",
|
||||||
allow: "autoplay; encrypted-media",
|
allow: "autoplay; encrypted-media",
|
||||||
referrerpolicy: "strict-origin-when-cross-origin",
|
referrerpolicy: "strict-origin-when-cross-origin",
|
||||||
@@ -1877,11 +1881,11 @@ const SlideCreator = {
|
|||||||
event.target.setPlaybackQuality(quality);
|
event.target.setPlaybackQuality(quality);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only play if this is the active slide
|
// Only play if this is the active slide and the play signal has been issued (delay finished)
|
||||||
const slide = document.querySelector(`.slide[data-item-id="${itemId}"]`);
|
const slide = document.querySelector(`.slide[data-item-id="${itemId}"]`);
|
||||||
const isVideoPlayerOpen = document.querySelector('.videoPlayerContainer') || document.querySelector('.youtubePlayerContainer');
|
const isVideoPlayerOpen = document.querySelector('.videoPlayerContainer') || document.querySelector('.youtubePlayerContainer');
|
||||||
|
|
||||||
if (slide && slide.classList.contains('active') && !document.hidden && (!isVideoPlayerOpen || isVideoPlayerOpen.classList.contains('hide'))) {
|
if (slide && slide.classList.contains('active') && STATE.slideshow.playSignals[itemId] === true && !document.hidden && (!isVideoPlayerOpen || isVideoPlayerOpen.classList.contains('hide'))) {
|
||||||
event.target.playVideo();
|
event.target.playVideo();
|
||||||
|
|
||||||
// Check if it actually started playing after a short delay (handling autoplay blocks)
|
// Check if it actually started playing after a short delay (handling autoplay blocks)
|
||||||
@@ -1914,8 +1918,14 @@ const SlideCreator = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
'onStateChange': (event) => {
|
'onStateChange': (event) => {
|
||||||
// Fade in when playing
|
|
||||||
if (event.data === YT.PlayerState.PLAYING) {
|
if (event.data === YT.PlayerState.PLAYING) {
|
||||||
|
const slide = document.querySelector(`.slide[data-item-id="${itemId}"]`);
|
||||||
|
if (slide && STATE.slideshow.playSignals[itemId] === false) {
|
||||||
|
event.target.pauseVideo();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fade in when legitimately playing
|
||||||
if (event.target._wrapperDiv) {
|
if (event.target._wrapperDiv) {
|
||||||
event.target._wrapperDiv.style.opacity = "1";
|
event.target._wrapperDiv.style.opacity = "1";
|
||||||
}
|
}
|
||||||
@@ -1970,6 +1980,11 @@ const SlideCreator = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (STATE.slideshow.playSignals[itemId] === false) {
|
||||||
|
event.target.pause();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Fade in
|
// Fade in
|
||||||
event.target.style.opacity = "1";
|
event.target.style.opacity = "1";
|
||||||
|
|
||||||
@@ -2055,7 +2070,7 @@ const SlideCreator = {
|
|||||||
SlideUtils.truncateText(plotElement, CONFIG.maxPlotLength);
|
SlideUtils.truncateText(plotElement, CONFIG.maxPlotLength);
|
||||||
|
|
||||||
const plotContainer = SlideUtils.createElement("div", {
|
const plotContainer = SlideUtils.createElement("div", {
|
||||||
className: "plot-container",
|
className: "plot-container" + (CONFIG.constrainPlotWidth ? " constrained-plot" : ""),
|
||||||
});
|
});
|
||||||
plotContainer.appendChild(plotElement);
|
plotContainer.appendChild(plotElement);
|
||||||
|
|
||||||
@@ -2443,6 +2458,11 @@ const SlideshowManager = {
|
|||||||
|
|
||||||
STATE.slideshow.isTransitioning = true;
|
STATE.slideshow.isTransitioning = true;
|
||||||
|
|
||||||
|
if (STATE.slideshow.backdropVideoTimeout) {
|
||||||
|
clearTimeout(STATE.slideshow.backdropVideoTimeout);
|
||||||
|
STATE.slideshow.backdropVideoTimeout = null;
|
||||||
|
}
|
||||||
|
|
||||||
let previousVisibleSlide;
|
let previousVisibleSlide;
|
||||||
try {
|
try {
|
||||||
const container = SlideUtils.getOrCreateSlidesContainer();
|
const container = SlideUtils.getOrCreateSlidesContainer();
|
||||||
@@ -2474,6 +2494,7 @@ const SlideshowManager = {
|
|||||||
|
|
||||||
void currentSlide.offsetWidth;
|
void currentSlide.offsetWidth;
|
||||||
currentSlide.classList.add("active");
|
currentSlide.classList.add("active");
|
||||||
|
STATE.slideshow.playSignals[currentItemId] = false;
|
||||||
|
|
||||||
// Manage Video Playback: Stop others, Play current
|
// Manage Video Playback: Stop others, Play current
|
||||||
// 1. Stop all other YouTube players and local video elements, release connections
|
// 1. Stop all other YouTube players and local video elements, release connections
|
||||||
@@ -2534,11 +2555,13 @@ const SlideshowManager = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (videoBackdrop) {
|
if (videoBackdrop) {
|
||||||
|
// preload logic
|
||||||
if (videoBackdrop.tagName === 'VIDEO') {
|
if (videoBackdrop.tagName === 'VIDEO') {
|
||||||
// Restore src from data-src if it was deactivated to release connections
|
// Restore src from data-src if it was deactivated to release connections
|
||||||
const lazySrc = videoBackdrop.getAttribute('data-src');
|
const lazySrc = videoBackdrop.getAttribute('data-src');
|
||||||
if (lazySrc && !videoBackdrop.src) {
|
if (lazySrc && !videoBackdrop.src) {
|
||||||
videoBackdrop.src = lazySrc;
|
videoBackdrop.src = lazySrc;
|
||||||
|
videoBackdrop.load(); // Force pre-buffering
|
||||||
}
|
}
|
||||||
|
|
||||||
videoBackdrop.currentTime = 0;
|
videoBackdrop.currentTime = 0;
|
||||||
@@ -2547,22 +2570,11 @@ const SlideshowManager = {
|
|||||||
if (!STATE.slideshow.isMuted) {
|
if (!STATE.slideshow.isMuted) {
|
||||||
videoBackdrop.volume = 0.4;
|
videoBackdrop.volume = 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
videoBackdrop.play().catch(e => {
|
|
||||||
// Check if it actually started playing after a short delay (handling autoplay blocks)
|
|
||||||
setTimeout(() => {
|
|
||||||
if (videoBackdrop.paused && currentSlide.classList.contains('active')) {
|
|
||||||
console.warn("🎬 Media Bar:", `Autoplay blocked for ${currentItemId}, attempting muted fallback`);
|
|
||||||
videoBackdrop.muted = true;
|
|
||||||
videoBackdrop.play().catch(err => console.error("🎬 Media Bar:", "Muted fallback failed", err));
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
});
|
|
||||||
} else if (STATE.slideshow.videoPlayers && STATE.slideshow.videoPlayers[currentItemId]) {
|
} else if (STATE.slideshow.videoPlayers && STATE.slideshow.videoPlayers[currentItemId]) {
|
||||||
const player = STATE.slideshow.videoPlayers[currentItemId];
|
const player = STATE.slideshow.videoPlayers[currentItemId];
|
||||||
if (player && typeof player.loadVideoById === 'function' && player._videoId) {
|
if (player && typeof player.cueVideoById === 'function' && player._videoId) {
|
||||||
// Use loadVideoById to enforce start and end times
|
// Use cueVideoById to buffer video without auto-playing it
|
||||||
player.loadVideoById({
|
player.cueVideoById({
|
||||||
videoId: player._videoId,
|
videoId: player._videoId,
|
||||||
startSeconds: player._startTime || 0,
|
startSeconds: player._startTime || 0,
|
||||||
endSeconds: player._endTime
|
endSeconds: player._endTime
|
||||||
@@ -2574,25 +2586,60 @@ const SlideshowManager = {
|
|||||||
player.unMute();
|
player.unMute();
|
||||||
player.setVolume(40);
|
player.setVolume(40);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if playback successfully started, otherwise fallback to muted
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!currentSlide.classList.contains('active')) return;
|
|
||||||
if (player.getPlayerState &&
|
|
||||||
player.getPlayerState() !== YT.PlayerState.PLAYING &&
|
|
||||||
player.getPlayerState() !== YT.PlayerState.BUFFERING) {
|
|
||||||
console.log("🎬 Media Bar:", "YouTube loadVideoById didn't start playback, retrying muted...");
|
|
||||||
player.mute();
|
|
||||||
player.playVideo();
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
} else if (player && typeof player.seekTo === 'function') {
|
} else if (player && typeof player.seekTo === 'function') {
|
||||||
// Fallback if loadVideoById is not available or videoId missing
|
|
||||||
const startTime = player._startTime || 0;
|
const startTime = player._startTime || 0;
|
||||||
player.seekTo(startTime);
|
player.seekTo(startTime);
|
||||||
player.playVideo();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// play logic
|
||||||
|
const playVideoLogic = () => {
|
||||||
|
if (!currentSlide.classList.contains('active')) return;
|
||||||
|
|
||||||
|
STATE.slideshow.playSignals[currentItemId] = true;
|
||||||
|
|
||||||
|
if (videoBackdrop.tagName === 'VIDEO') {
|
||||||
|
videoBackdrop.play().catch(e => {
|
||||||
|
if (!STATE.slideshow.isMuted) {
|
||||||
|
// Check if it actually started playing after a short delay (handling autoplay blocks)
|
||||||
|
setTimeout(() => {
|
||||||
|
if (videoBackdrop.paused && currentSlide.classList.contains('active')) {
|
||||||
|
console.warn("🎬 Media Bar:", `Autoplay blocked for ${currentItemId}, attempting muted fallback`);
|
||||||
|
videoBackdrop.muted = true;
|
||||||
|
videoBackdrop.play().catch(err => console.error("🎬 Media Bar:", "Muted fallback failed", err));
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
console.error("🎬 Media Bar:", "Playback failed despite being muted", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (STATE.slideshow.videoPlayers && STATE.slideshow.videoPlayers[currentItemId]) {
|
||||||
|
const player = STATE.slideshow.videoPlayers[currentItemId];
|
||||||
|
if (player && typeof player.playVideo === 'function') {
|
||||||
|
player.playVideo();
|
||||||
|
|
||||||
|
if (!STATE.slideshow.isMuted) {
|
||||||
|
// Check if playback successfully started, otherwise fallback to muted
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!currentSlide.classList.contains('active')) return;
|
||||||
|
if (player.getPlayerState &&
|
||||||
|
player.getPlayerState() !== YT.PlayerState.PLAYING &&
|
||||||
|
player.getPlayerState() !== YT.PlayerState.BUFFERING) {
|
||||||
|
console.log("🎬 Media Bar:", "YouTube didn't start playback, retrying muted...");
|
||||||
|
player.mute();
|
||||||
|
player.playVideo();
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (CONFIG.backdropVideoDelay > 0) {
|
||||||
|
STATE.slideshow.backdropVideoTimeout = setTimeout(playVideoLogic, CONFIG.backdropVideoDelay);
|
||||||
|
} else {
|
||||||
|
playVideoLogic();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const enableAnimations = MediaBarEnhancedSettingsManager.getSetting('slideAnimations', CONFIG.slideAnimationEnabled);
|
const enableAnimations = MediaBarEnhancedSettingsManager.getSetting('slideAnimations', CONFIG.slideAnimationEnabled);
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ Bevor du baust, musst du die Versionsnummer in den folgenden Dateien aktualisier
|
|||||||
|
|
||||||
Führe den folgenden Befehl im Terminal (PowerShell) im Hauptverzeichnis aus. Wir nutzen hier `dotnet build` statt `publish`, um unnötige Dateien zu vermeiden.
|
Führe den folgenden Befehl im Terminal (PowerShell) im Hauptverzeichnis aus. Wir nutzen hier `dotnet build` statt `publish`, um unnötige Dateien zu vermeiden.
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
dotnet build Jellyfin.Plugin.MediaBarEnhanced/Jellyfin.Plugin.MediaBarEnhanced.csproj --configuration Release --output bin/Publish;
|
||||||
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
dotnet build Jellyfin.Plugin.MediaBarEnhanced/Jellyfin.Plugin.MediaBarEnhanced.csproj --configuration Release --output bin/Publish; Compress-Archive -Path bin/Publish/* -DestinationPath bin/Publish/Jellyfin.Plugin.MediaBarEnhanced.zip -Force; $hash = (Get-FileHash -Algorithm MD5 bin/Publish/Jellyfin.Plugin.MediaBarEnhanced.zip).Hash.ToLower(); $time = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"); Write-Output "`n----------------------------------------"; Write-Output "NEUE CHECKSUMME (MD5): $hash"; Write-Output "ZEITSTEMPEL: $time"; Write-Output "----------------------------------------`n"
|
dotnet build Jellyfin.Plugin.MediaBarEnhanced/Jellyfin.Plugin.MediaBarEnhanced.csproj --configuration Release --output bin/Publish; Compress-Archive -Path bin/Publish/* -DestinationPath bin/Publish/Jellyfin.Plugin.MediaBarEnhanced.zip -Force; $hash = (Get-FileHash -Algorithm MD5 bin/Publish/Jellyfin.Plugin.MediaBarEnhanced.zip).Hash.ToLower(); $time = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"); Write-Output "`n----------------------------------------"; Write-Output "NEUE CHECKSUMME (MD5): $hash"; Write-Output "ZEITSTEMPEL: $time"; Write-Output "----------------------------------------`n"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -9,16 +9,16 @@
|
|||||||
"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.8.1.2",
|
"version": "1.9.0.0",
|
||||||
"changelog": "fix pagination dot issue on mobile when showing more than 10 dots (should now dynamically adjust the max dots threshold based on screen size)",
|
"changelog": "- fix pagination dot issue on mobile when showing more than 10 dots (should now dynamically adjust the max dots threshold based on screen size)\n- add option to delay trailer playback\n- add option to limit the plot width",
|
||||||
"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.8.1.2/Jellyfin.Plugin.MediaBarEnhanced.zip",
|
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/releases/download/v1.9.0.0/Jellyfin.Plugin.MediaBarEnhanced.zip",
|
||||||
"checksum": "5ca1f5b5ad5dd20d521533b815aec656",
|
"checksum": "de2c736f754788eeb881aaa4fafa692f",
|
||||||
"timestamp": "2026-03-23T17:35:37Z"
|
"timestamp": "2026-03-24T01:27:06Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"version": "1.8.0.0",
|
"version": "1.8.0.0",
|
||||||
"changelog": "feat: add custom text/image overlay option\n- feat: add option to disable pagination dots/counter\n- feat: add exclude seasonal content from random fetching option\n- Add hide arrows on mobile option \n- fix button issue on mobile when using ElegantFin Theme",
|
"changelog": "- feat: add custom text/image overlay option\n- feat: add option to disable pagination dots/counter\n- feat: add exclude seasonal content from random fetching option\n- Add hide arrows on mobile option \n- fix button issue on mobile when using ElegantFin Theme",
|
||||||
"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.8.0.0/Jellyfin.Plugin.MediaBarEnhanced.zip",
|
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/releases/download/v1.8.0.0/Jellyfin.Plugin.MediaBarEnhanced.zip",
|
||||||
"checksum": "0aac723796d41fc15987c94ac0476584",
|
"checksum": "0aac723796d41fc15987c94ac0476584",
|
||||||
|
|||||||
Reference in New Issue
Block a user