mirror of
https://github.com/IAmParadox27/jellyfin-plugin-media-bar.git
synced 2026-11-06 23:58:39 +01:00
Merge branch 'MakD:main' into main
This commit is contained in:
@@ -124,6 +124,16 @@ Here I present my version of the same with some code improvements, loading optim
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>main.jellyfin.bundle.js</summary>
|
||||
|
||||
1. Similarly, search for `main.jellyfin.bundle.js` in the `jellyfin-web` directory. Open it with any code editor with administrator privileges.
|
||||
2. Search for `this.playbackManager = e;`
|
||||
3. Right after the `;`, paste the code block `window.PlaybackManager = this.playbackManager;console.log("PlaybackManager is now globally available:", window.PlaybackManager);`
|
||||
|
||||
</details>
|
||||
|
||||
And that is it. Hard refresh your web page (CTRL+Shift+R) twice, and Profit!
|
||||
|
||||
# Want a Custom List to be showcased instead of random items??
|
||||
|
||||
+73
-160
@@ -54,11 +54,11 @@
|
||||
}
|
||||
|
||||
.left-arrow {
|
||||
left: 10px;
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
.right-arrow {
|
||||
right: 10px;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
.dots-container {
|
||||
@@ -104,12 +104,11 @@
|
||||
|
||||
#slides-container {
|
||||
position: relative;
|
||||
width: 100vw;
|
||||
height: 750px;
|
||||
width: 92vw;
|
||||
height: 650px;
|
||||
overflow: hidden;
|
||||
margin: 0 auto;
|
||||
border-radius: 7px;
|
||||
top: -5em;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.slide {
|
||||
@@ -223,7 +222,7 @@
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
color: #fff;
|
||||
width: 50%;
|
||||
width: 90%;
|
||||
height: 60%;
|
||||
font-size: 15px;
|
||||
padding: 10px 0 25px 15px;
|
||||
@@ -342,93 +341,54 @@
|
||||
font-size: 10px;
|
||||
color: aquamarine;
|
||||
}
|
||||
.play-button {
|
||||
.button-container {
|
||||
position: absolute;
|
||||
top: calc(50% + 190px); /* Same as the previous button positions */
|
||||
left: 7.5em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px 20px;
|
||||
color: #fff;
|
||||
background-color: rgba(255, 255, 255, 0);
|
||||
border: none;
|
||||
border-radius: 50px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 300;
|
||||
transition: background-color 0.3s;
|
||||
z-index: 4;
|
||||
top: calc(50% + 190px);
|
||||
left: 6.8em;
|
||||
}
|
||||
|
||||
.play-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background-color: rgba(
|
||||
12,
|
||||
110,
|
||||
162,
|
||||
0.7
|
||||
);
|
||||
border: 3px solid rgba(12, 110, 162, 1);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.play-text {
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
margin-left: 10px;
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
gap: 2em; /* Space between buttons */
|
||||
z-index: 5; /* Ensures it's above other elements */
|
||||
}
|
||||
.play-button,
|
||||
.detail-button {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
display: inline-flex; /* Ensures icon and text are on the same line */
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px 20px;
|
||||
color: #fff;
|
||||
background-color: rgba(255, 255, 255, 0);
|
||||
border: none;
|
||||
border-radius: 50px;
|
||||
padding: 8px 16px; /* Slightly reduced padding for thinner buttons */
|
||||
border: solid 2px;
|
||||
border-radius: 25px; /* Sleeker look */
|
||||
font-size: 14px;
|
||||
white-space: nowrap; /* Prevents text wrapping */
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 300;
|
||||
transition: background-color 0.3s;
|
||||
z-index: 4;
|
||||
top: calc(50% + 190px);
|
||||
left: 15.8em;
|
||||
transition: all 0.3s ease;
|
||||
font-weight: bold;
|
||||
gap: 6px; /* Adds space between icon and text */
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.play-button {
|
||||
background-color: #ffffff;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.detail-button {
|
||||
background-color: rgba(255, 255, 255, 0);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.play-button:hover,
|
||||
.detail-button:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.play-icon,
|
||||
.detail-icon {
|
||||
font-size: 18px; /* Ensures icons are aligned with text */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background-color: rgba(
|
||||
12,
|
||||
110,
|
||||
162,
|
||||
0.7
|
||||
);
|
||||
border: 3px solid rgba(12, 110, 162, 1);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.detail-text {
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
margin-left: 10px;
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
.backdrop,
|
||||
.slide {
|
||||
@@ -676,99 +636,52 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.play-button {
|
||||
.button-container {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 10px 20px;
|
||||
color: #fff;
|
||||
background-color: rgba(255, 255, 255, 0);
|
||||
border: none;
|
||||
border-radius: 50px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 300;
|
||||
transition: background-color 0.3s;
|
||||
z-index: 4;
|
||||
bottom: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-110%) scale(1.2);
|
||||
outline: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.play-icon {
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: rgba(
|
||||
12,
|
||||
110,
|
||||
162,
|
||||
0.7
|
||||
);
|
||||
border: 1.5px solid rgba(12, 110, 162, 1);
|
||||
border-radius: 50%;
|
||||
outline: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
gap: 15px; /* Adjust spacing between buttons */
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.play-text {
|
||||
display: block;
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
margin-left: 5px;
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
}
|
||||
.play-button,
|
||||
.detail-button {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 10px 20px;
|
||||
color: #fff;
|
||||
background-color: rgba(255, 255, 255, 0);
|
||||
border: none;
|
||||
border-radius: 50px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 300;
|
||||
transition: background-color 0.3s;
|
||||
z-index: 4;
|
||||
bottom: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(10%) scale(1.2);
|
||||
outline: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.detail-icon {
|
||||
display: flex;
|
||||
display: inline-flex; /* Ensures icon and text are on the same line */
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: rgba(
|
||||
12,
|
||||
110,
|
||||
162,
|
||||
0.7
|
||||
);
|
||||
border: 1.5px solid rgba(12, 110, 162, 1);
|
||||
border-radius: 50%;
|
||||
outline: none;
|
||||
padding: 8px 16px; /* Slightly reduced padding for thinner buttons */
|
||||
border: none;
|
||||
border-radius: 20px; /* Sleeker look */
|
||||
font-size: 14px;
|
||||
white-space: nowrap; /* Prevents text wrapping */
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
font-weight: bold;
|
||||
gap: 6px; /* Adds space between icon and text */
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.detail-text {
|
||||
display: block;
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
margin-left: 5px;
|
||||
.play-button {
|
||||
background-color: #ffffff;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.detail-button {
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.play-button:hover,
|
||||
.detail-button:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.play-icon,
|
||||
.detail-icon {
|
||||
font-size: 18px; /* Ensures icons are aligned with text */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
+50
-31
@@ -5,8 +5,8 @@ const slidesInit = () => {
|
||||
const jsonCredentials = sessionStorage.getItem("json-credentials");
|
||||
let userId = null;
|
||||
let token = null;
|
||||
const deviceId = localStorage.getItem("_deviceId2");
|
||||
console.log(deviceId);
|
||||
//const deviceId = localStorage.getItem("_deviceId2");
|
||||
//console.log(deviceId);
|
||||
if (jsonCredentials) {
|
||||
const credentials = JSON.parse(jsonCredentials);
|
||||
userId = credentials.Servers[0].UserId;
|
||||
@@ -165,59 +165,78 @@ const slidesInit = () => {
|
||||
const infoContainer = document.createElement("div");
|
||||
infoContainer.className = "info-container";
|
||||
infoContainer.appendChild(ratingTest);
|
||||
// Create a container for the buttons
|
||||
const buttonContainer = document.createElement("div");
|
||||
buttonContainer.className = "button-container"; // Add a class for styling
|
||||
|
||||
// Create the Play button
|
||||
const playButton = document.createElement("button");
|
||||
playButton.className = "play-button";
|
||||
playButton.innerHTML = `
|
||||
<span class="play-icon"><i class="material-icons play_circle_outline"></i></span>
|
||||
<span class="play-text">Play Now</span>
|
||||
`;
|
||||
<span class="play-icon"><i class="material-icons play_circle_outline"></i></span>
|
||||
<span class="play-text">Play</span>
|
||||
`;
|
||||
playButton.onclick = async () => {
|
||||
if (!window.PlaybackManager) {
|
||||
console.error("PlaybackManager is not available.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!window.ApiClient) {
|
||||
console.error("Jellyfin API client is not available.");
|
||||
return;
|
||||
}
|
||||
|
||||
const apiClient = window.ApiClient;
|
||||
const userId = apiClient.getCurrentUserId();
|
||||
|
||||
if (!userId) {
|
||||
console.error("User not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const sessions = await apiClient.getJSON(
|
||||
apiClient.serverAddress() + "/Sessions"
|
||||
);
|
||||
if (!sessions.length) {
|
||||
console.error("No active Jellyfin sessions found.");
|
||||
// Fetch the media item details
|
||||
const item = await apiClient.getItem(userId, itemId);
|
||||
if (!item) {
|
||||
console.error("Media item not found.");
|
||||
return;
|
||||
}
|
||||
const sessionId = sessions[0].Id;
|
||||
const playbackUrl = `${apiClient.serverAddress()}/Sessions/${sessionId}/Playing?StartPositionTicks=0&PlayCommand=PlayNow&StartIndex=0&ItemIds=${itemId}&api_key=${token}`;
|
||||
const response = await fetch(playbackUrl, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `MediaBrowser Client="Jellyfin Web", Device="YourDevice", DeviceId="YourDeviceId", Version="YourVersion", Token="${token}"`,
|
||||
},
|
||||
});
|
||||
if (response.status === 204) {
|
||||
console.log("Playback started successfully.");
|
||||
} else {
|
||||
const errorData = await response.json();
|
||||
console.error("Failed to start playback:", errorData);
|
||||
}
|
||||
|
||||
// Initiate playback using PlaybackManager
|
||||
window.PlaybackManager.play({
|
||||
items: [item],
|
||||
startPositionTicks: 0, // Start from beginning
|
||||
isMuted: false,
|
||||
isPaused: false,
|
||||
})
|
||||
.then(() => {
|
||||
console.log("Playback started successfully.");
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Failed to start playback:", error);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error fetching sessions:", error);
|
||||
console.error("Error starting playback:", error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create the Details button
|
||||
const detailButton = document.createElement("button");
|
||||
detailButton.className = "detail-button";
|
||||
detailButton.innerHTML = `
|
||||
<span class="detail-icon"><i class="material-icons info_outline"></i></span>
|
||||
<span class="detail-text">More Details</span>
|
||||
`;
|
||||
<span class="detail-icon"><i class="material-icons info_outline"></i></span>
|
||||
<span class="detail-text">Info</span>
|
||||
`;
|
||||
detailButton.onclick = () => {
|
||||
window.top.location.href = `/#!/details?id=${itemId}`;
|
||||
};
|
||||
|
||||
// Append buttons to the button container
|
||||
buttonContainer.appendChild(playButton);
|
||||
buttonContainer.appendChild(detailButton);
|
||||
|
||||
// Append all elements to the slide
|
||||
slide.append(
|
||||
logoContainer,
|
||||
backdropContainer,
|
||||
@@ -226,9 +245,9 @@ const slidesInit = () => {
|
||||
plotContainer,
|
||||
infoContainer,
|
||||
genreElement,
|
||||
playButton,
|
||||
detailButton
|
||||
buttonContainer
|
||||
);
|
||||
|
||||
return slide;
|
||||
};
|
||||
const createSlideForItem = async (item, title) => {
|
||||
|
||||
Reference in New Issue
Block a user