mirror of
https://github.com/IAmParadox27/jellyfin-plugin-media-bar.git
synced 2026-11-08 00:20:59 +01:00
Initial Release
This commit is contained in:
@@ -0,0 +1,685 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=Titillium+Web:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700&display=swap");
|
||||
|
||||
@media only screen and (min-width: 767px) {
|
||||
div[data-role="page"].page {
|
||||
overflow-y: scroll; /* Keeps vertical scrolling active */
|
||||
scrollbar-width: none; /* For Firefox */
|
||||
-ms-overflow-style: none; /* For Internet Explorer & Edge */
|
||||
}
|
||||
|
||||
div[data-role="page"].page::-webkit-scrollbar {
|
||||
display: none; /* Hides scrollbar in Webkit browsers */
|
||||
}
|
||||
|
||||
.backdrop,
|
||||
.slide {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.featured-content,
|
||||
.plot-container {
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.plot,
|
||||
body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
z-index: 3;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.arrow::before {
|
||||
content: ""; /* Creates an empty element */
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 40px; /* Size of the circle */
|
||||
height: 40px; /* Size of the circle */
|
||||
background-color: rgba(12, 110, 162, 0.7); /* Translucent background */
|
||||
border-radius: 50%; /* Makes it a circle */
|
||||
z-index: -1; /* Places the circle behind the arrow */
|
||||
}
|
||||
|
||||
.left-arrow {
|
||||
left: 10px; /* Position to the left */
|
||||
}
|
||||
|
||||
.right-arrow {
|
||||
right: 10px; /* Position to the right */
|
||||
}
|
||||
|
||||
.dots-container {
|
||||
position: absolute;
|
||||
bottom: 5%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
justify-content: center; /* Centers the dots horizontally */
|
||||
align-items: center;
|
||||
width: 100vw; /* Full screen width */
|
||||
height: 22px;
|
||||
background-color: #ffffff00;
|
||||
gap: 2vw; /* Evenly space the rectangles with a gap of 2vw */
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 15vw; /* Each rectangle takes 18% of the viewport width */
|
||||
height: 4px; /* Thin rectangle height */
|
||||
background-color: #cecece;
|
||||
border-radius: 2px; /* Slightly rounded corners */
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.dot.active {
|
||||
background-color: rgba(12, 110, 162, 0.7) !important;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.fade-in {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.fade-out {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
#slides-container {
|
||||
position: relative;
|
||||
width: 100vw;
|
||||
height: 750px;
|
||||
overflow: hidden;
|
||||
margin: 0 auto;
|
||||
border-radius: 7px;
|
||||
top: -5em;
|
||||
}
|
||||
|
||||
.slide {
|
||||
transition: opacity 0.5s ease-in-out; /* Smooth fade transition */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.slide.active {
|
||||
opacity: 1;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.slide:focus {
|
||||
outline: #fff solid 2px;
|
||||
}
|
||||
|
||||
.backdrop-container {
|
||||
position: relative;
|
||||
top: -40%;
|
||||
right: -35%;
|
||||
width: 70%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.backdrop {
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center 20%;
|
||||
border-radius: 5px;
|
||||
z-index: 1;
|
||||
mask-image: linear-gradient(
|
||||
to top,
|
||||
rgba(0, 0, 0, 0) 10%,
|
||||
rgba(0, 0, 0, 0.5) 15%,
|
||||
rgba(0, 0, 0, 1) 30%
|
||||
);
|
||||
-webkit-mask-image: linear-gradient(
|
||||
to top,
|
||||
rgba(0, 0, 0, 0) 10%,
|
||||
rgba(0, 0, 0, 0.5) 15%,
|
||||
rgba(0, 0, 0, 1) 30%
|
||||
);
|
||||
}
|
||||
|
||||
.backdrop-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.6); /* Adjust the alpha for dimness */
|
||||
border-radius: 5px;
|
||||
z-index: 2;
|
||||
mask-image: linear-gradient(
|
||||
to top,
|
||||
rgba(0, 0, 0, 0) 10%,
|
||||
rgba(0, 0, 0, 0.5) 15%,
|
||||
rgba(0, 0, 0, 1) 30%
|
||||
);
|
||||
-webkit-mask-image: linear-gradient(
|
||||
to top,
|
||||
rgba(0, 0, 0, 0) 10%,
|
||||
rgba(0, 0, 0, 0.5) 15%,
|
||||
rgba(0, 0, 0, 1) 30%
|
||||
);
|
||||
}
|
||||
|
||||
.logo-container {
|
||||
width: 45%;
|
||||
height: 40%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: left;
|
||||
}
|
||||
|
||||
.logo {
|
||||
position: relative;
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
width: auto;
|
||||
z-index: 3;
|
||||
top: 5em;
|
||||
left: 8em;
|
||||
}
|
||||
|
||||
.featured-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
background-color: transparent;
|
||||
color: #d3d3d3;
|
||||
font-size: 22px;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.plot-container {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
color: #fff;
|
||||
width: 50%;
|
||||
height: 60%;
|
||||
font-size: 15px;
|
||||
padding: 10px 0 25px 15px;
|
||||
border-radius: 5px;
|
||||
z-index: 3;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
.plot {
|
||||
display: -webkit-box;
|
||||
line-clamp: 4;
|
||||
-webkit-line-clamp: 4;
|
||||
-webkit-box-orient: vertical;
|
||||
left: 7.9em;
|
||||
position: absolute;
|
||||
top: 190px;
|
||||
}
|
||||
|
||||
.gradient-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 70%;
|
||||
height: 100%;
|
||||
background: linear-gradient(to right, #000 49%, rgba(0, 0, 0, 0) 70%);
|
||||
z-index: 2;
|
||||
mask-image: linear-gradient(
|
||||
to top,
|
||||
rgba(0, 0, 0, 0) 8%,
|
||||
rgba(0, 0, 0, 0.5) 10%,
|
||||
rgba(0, 0, 0, 1) 12%
|
||||
);
|
||||
-webkit-mask-image: linear-gradient(
|
||||
to top,
|
||||
rgba(0, 0, 0, 0) 8%,
|
||||
rgba(0, 0, 0, 0.5) 10%,
|
||||
rgba(0, 0, 0, 1) 12%
|
||||
);
|
||||
}
|
||||
.genre {
|
||||
position: absolute;
|
||||
top: calc(50% + 75px);
|
||||
left: 8.4em;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
font-size: 14px;
|
||||
z-index: 4;
|
||||
}
|
||||
.info-container {
|
||||
position: absolute;
|
||||
top: calc(50% + 0px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
left: 2em !important;
|
||||
color: #fff;
|
||||
z-index: 4;
|
||||
}
|
||||
.rating-value {
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 6em;
|
||||
z-index: 5;
|
||||
position: relative;
|
||||
top: 1.5em;
|
||||
}
|
||||
.runTime {
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 8px;
|
||||
margin-right: -3px;
|
||||
}
|
||||
.rating-value img {
|
||||
margin-right: 6px;
|
||||
}
|
||||
.tomato-rating {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 0;
|
||||
}
|
||||
.tomato-rating img {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.age-rating {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
border-radius: 5px;
|
||||
background: rgb(255 255 255 / 0.8);
|
||||
color: #000;
|
||||
border: none;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
padding: 0 0.6em;
|
||||
}
|
||||
.date {
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 5px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
.separator-icon {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
font-size: 10px;
|
||||
color: aquamarine;
|
||||
}
|
||||
.play-button {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center; /* Center vertically */
|
||||
justify-content: center; /* Keep content aligned horizontally */
|
||||
padding: 10px 20px;
|
||||
color: #fff;
|
||||
background-color: rgba(255, 255, 255, 0);
|
||||
border: none;
|
||||
border-radius: 50px; /* Round the edges */
|
||||
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; /* Adjust the size of the play icon */
|
||||
width: 30px; /* Ensure the icon area is circular */
|
||||
height: 30px;
|
||||
background-color: rgba(
|
||||
12,
|
||||
110,
|
||||
162,
|
||||
0.7
|
||||
); /* Same as the button's background */
|
||||
border: 3px solid rgba(12, 110, 162, 1);
|
||||
border-radius: 50%; /* Make the icon a perfect circle */
|
||||
}
|
||||
|
||||
.play-text {
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
margin-left: 10px; /* Space between icon and text */
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
.backdrop,
|
||||
.slide {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
position: absolute;
|
||||
/*top: 50%;
|
||||
transform: translateY(-50%);*/
|
||||
bottom: 25px;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
z-index: 4;
|
||||
-webkit-tap-highlight-color: transparent; /* Disable blue tap highlight */
|
||||
}
|
||||
|
||||
.left-arrow {
|
||||
left: 10px; /* Position to the left */
|
||||
}
|
||||
|
||||
.right-arrow {
|
||||
right: 10px; /* Position to the right */
|
||||
}
|
||||
|
||||
.featured-content,
|
||||
.plot-container {
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.plot,
|
||||
body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.fade-in {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.fade-out {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
.dots-container {
|
||||
position: absolute;
|
||||
bottom: 11%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) scale(0.6);
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
background-color: #ffffff00;
|
||||
border-radius: 50px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 140px;
|
||||
height: 22px;
|
||||
transition: opacity 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.dot {
|
||||
display: inline-block;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
margin: 0 5px;
|
||||
background-color: #cecece;
|
||||
border-radius: 50%;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.dot.active {
|
||||
width: 32px;
|
||||
height: 12px;
|
||||
background-color: rgba(12, 110, 162, 0.7);
|
||||
border-radius: 10px; /* Rounded rectangle shape */
|
||||
}
|
||||
|
||||
#slides-container {
|
||||
position: relative;
|
||||
width: 92vw;
|
||||
height: 650px;
|
||||
overflow: hidden;
|
||||
margin: 0 auto;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.slide {
|
||||
transition: opacity 0.5s ease-in-out; /* Smooth fade transition */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.slide.active {
|
||||
opacity: 1;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.slide:focus {
|
||||
outline: #fff solid 2px;
|
||||
}
|
||||
.logo {
|
||||
position: absolute;
|
||||
bottom: 28%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
max-height: 60%;
|
||||
max-width: 80%;
|
||||
width: auto;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.backdrop {
|
||||
position: absolute;
|
||||
top: 45px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
object-fit: cover;
|
||||
object-position: center 20%;
|
||||
z-index: 1;
|
||||
border-radius: 13px;
|
||||
mask-image: linear-gradient(
|
||||
to top,
|
||||
rgba(0, 0, 0, 0) 10%,
|
||||
rgba(0, 0, 0, 0.5) 15%,
|
||||
rgba(0, 0, 0, 1) 30%
|
||||
);
|
||||
-webkit-mask-image: linear-gradient(
|
||||
to top,
|
||||
rgba(0, 0, 0, 0) 10%,
|
||||
rgba(0, 0, 0, 0.5) 15%,
|
||||
rgba(0, 0, 0, 1) 30%
|
||||
);
|
||||
}
|
||||
|
||||
.gradient-overlay {
|
||||
position: absolute;
|
||||
top: 45px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
background: rgba(0, 0, 0, 0.55); /* Semi-transparent overlay color */
|
||||
z-index: 2;
|
||||
border-radius: 13px;
|
||||
pointer-events: none;
|
||||
mask-image: linear-gradient(
|
||||
to top,
|
||||
rgba(0, 0, 0, 0) 10%,
|
||||
rgba(0, 0, 0, 0.5) 15%,
|
||||
rgba(0, 0, 0, 1) 30%
|
||||
);
|
||||
-webkit-mask-image: linear-gradient(
|
||||
to top,
|
||||
rgba(0, 0, 0, 0) 10%,
|
||||
rgba(0, 0, 0, 0.5) 15%,
|
||||
rgba(0, 0, 0, 1) 30%
|
||||
);
|
||||
}
|
||||
|
||||
.genre {
|
||||
position: absolute;
|
||||
bottom: 16%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
width: 90%;
|
||||
max-width: 100%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
font-size: 1.1em;
|
||||
font-weight: 500;
|
||||
z-index: 4;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.info-container {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
bottom: 20%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
font-size: 1.1em;
|
||||
color: #fff;
|
||||
z-index: 5;
|
||||
width: 100%;
|
||||
}
|
||||
.rating-value {
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.date {
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 2px;
|
||||
}
|
||||
.tomato-rating {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.tomato-logo {
|
||||
margin-right: 3px;
|
||||
}
|
||||
.critic-logo {
|
||||
margin-left: 3px;
|
||||
}
|
||||
.imdb-logo {
|
||||
margin-right: 3px;
|
||||
}
|
||||
.age-rating {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 5px;
|
||||
background: rgb(255 255 255 / 0.8);
|
||||
color: #000;
|
||||
border: none;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
padding: 0 0.4em;
|
||||
}
|
||||
.separator-icon {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
font-size: 1px;
|
||||
color: aquamarine;
|
||||
}
|
||||
.featured-content,
|
||||
.plot {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.play-button {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center; /* Center vertically */
|
||||
justify-content: flex-start; /* Keep content aligned horizontally */
|
||||
padding: 10px 20px;
|
||||
color: #fff;
|
||||
background-color: rgba(255, 255, 255, 0);
|
||||
border: none;
|
||||
border-radius: 50px; /* Round the edges */
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 300;
|
||||
transition: background-color 0.3s;
|
||||
z-index: 4;
|
||||
bottom: 20px;
|
||||
/*right: 0%;*/
|
||||
left: 50%;
|
||||
transform: translateX(-50%) scale(1.2);
|
||||
outline: none; /* Remove the default blue focus outline */
|
||||
-webkit-tap-highlight-color: transparent; /* Disable blue tap highlight */
|
||||
}
|
||||
|
||||
.play-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px; /* Adjust the size of the play icon */
|
||||
width: 20px; /* Ensure the icon area is circular */
|
||||
height: 20px;
|
||||
background-color: rgba(
|
||||
12,
|
||||
110,
|
||||
162,
|
||||
0.7
|
||||
); /* Same as the button's background */
|
||||
border: 1.5px solid rgba(12, 110, 162, 1);
|
||||
border-radius: 50%; /* Make the icon a perfect circle */
|
||||
outline: none; /* Remove the default blue focus outline */
|
||||
-webkit-tap-highlight-color: transparent; /* Disable blue tap highlight */
|
||||
}
|
||||
|
||||
.play-text {
|
||||
display: block;
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
margin-left: 5px; /* Space between icon and text */
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,427 @@
|
||||
const slidesInit = () => {
|
||||
const shuffleInterval = 8000;
|
||||
let isTransitioning = false;
|
||||
const listFileName = `${window.location.origin}/web/avatars/list.txt`;
|
||||
const jsonCredentials = sessionStorage.getItem("json-credentials");
|
||||
const apiKey = sessionStorage.getItem("api-key");
|
||||
const serverId = '4810878e0ca94ff0b08cd0df6e483c4f';
|
||||
let userId = null;
|
||||
let token = null;
|
||||
const deviceId = localStorage.getItem("_deviceId2");
|
||||
console.log(deviceId);
|
||||
if (jsonCredentials) {
|
||||
const credentials = JSON.parse(jsonCredentials);
|
||||
userId = credentials.Servers[0].UserId;
|
||||
token = credentials.Servers[0].AccessToken;
|
||||
}
|
||||
const shuffleArray = (array) => array.sort(() => Math.random() - 0.5);
|
||||
const truncateText = (element, maxLength) => {
|
||||
let text = element.innerText;
|
||||
if (text.length > maxLength)
|
||||
element.innerText = text.substring(0, maxLength) + "...";
|
||||
};
|
||||
const createSlideElement = (item, title) => {
|
||||
const itemId = item.Id;
|
||||
const plot = item.Overview || "No overview available";
|
||||
const rating = item.CommunityRating;
|
||||
const tomato = item.CriticRating;
|
||||
const runtime = item.RunTimeTicks;
|
||||
const genre = item.Genres;
|
||||
const youtube = item.RemoteTrailers;
|
||||
const age = item.OfficialRating;
|
||||
const date = item.PremiereDate;
|
||||
const season = item.ChildCount;
|
||||
function createSeparator() {
|
||||
const separatorHtml =
|
||||
'<i class="material-icons radio_button_off separator-icon"></i>';
|
||||
const tempDiv = document.createElement("div");
|
||||
tempDiv.innerHTML = separatorHtml;
|
||||
return tempDiv.firstChild;
|
||||
}
|
||||
const slide = document.createElement("a");
|
||||
slide.className = "slide";
|
||||
slide.target = "_top";
|
||||
slide.rel = "noreferrer";
|
||||
slide.tabIndex = 0;
|
||||
slide.style.display = "none";
|
||||
const backdrop = document.createElement("img");
|
||||
backdrop.className = "backdrop";
|
||||
backdrop.src = `${window.location.origin}/Items/${itemId}/Images/Backdrop/0`;
|
||||
backdrop.alt = "Backdrop";
|
||||
const backdropOverlay = document.createElement("div");
|
||||
backdropOverlay.className = "backdrop-overlay";
|
||||
const backdropContainer = document.createElement("div");
|
||||
backdropContainer.className = "backdrop-container";
|
||||
backdropContainer.appendChild(backdrop);
|
||||
backdropContainer.appendChild(backdropOverlay);
|
||||
const logo = document.createElement("img");
|
||||
logo.className = "logo";
|
||||
logo.src = `${window.location.origin}/Items/${itemId}/Images/Logo`;
|
||||
logo.alt = "Logo";
|
||||
const logoContainer = document.createElement("div");
|
||||
logoContainer.className = "logo-container";
|
||||
logoContainer.appendChild(logo);
|
||||
const featuredContent = document.createElement("div");
|
||||
featuredContent.className = "featured-content";
|
||||
featuredContent.textContent = title;
|
||||
const plotElement = document.createElement("div");
|
||||
plotElement.className = "plot";
|
||||
plotElement.textContent = plot;
|
||||
truncateText(plotElement, 360);
|
||||
const plotContainer = document.createElement("div");
|
||||
plotContainer.className = "plot-container";
|
||||
plotContainer.appendChild(plotElement);
|
||||
const gradientOverlay = document.createElement("div");
|
||||
gradientOverlay.className = "gradient-overlay";
|
||||
const runTimeElement = document.createElement("div");
|
||||
runTimeElement.className = "runTime";
|
||||
if (season === undefined) {
|
||||
const milliseconds = runtime / 10000;
|
||||
const currentTime = new Date();
|
||||
const endTime = new Date(currentTime.getTime() + milliseconds);
|
||||
const options = { hour: "2-digit", minute: "2-digit", hour12: !0 };
|
||||
const formattedEndTime = endTime.toLocaleTimeString([], options);
|
||||
runTimeElement.textContent = `Ends at ${formattedEndTime}`;
|
||||
} else {
|
||||
runTimeElement.textContent = `${season} Season${season > 1 ? "s" : ""}`;
|
||||
}
|
||||
const ratingTest = document.createElement("div");
|
||||
ratingTest.className = "rating-value";
|
||||
const imdbLogo = document.createElement("img");
|
||||
imdbLogo.className = "imdb-logo";
|
||||
imdbLogo.src =
|
||||
"https://upload.wikimedia.org/wikipedia/commons/6/69/IMDB_Logo_2016.svg";
|
||||
imdbLogo.alt = "IMDb Logo";
|
||||
imdbLogo.style.width = "30px";
|
||||
imdbLogo.style.height = "30px";
|
||||
ratingTest.appendChild(imdbLogo);
|
||||
if (typeof rating === "number") {
|
||||
const formattedRating = rating.toFixed(1);
|
||||
ratingTest.innerHTML += `${formattedRating} ⭐`;
|
||||
} else {
|
||||
console.error("Rating is undefined or not a number:", rating);
|
||||
ratingTest.innerHTML += `N/A ⭐`;
|
||||
}
|
||||
ratingTest.appendChild(createSeparator());
|
||||
const tomatoRatingDiv = document.createElement("div");
|
||||
tomatoRatingDiv.className = "tomato-rating";
|
||||
const criticRating = item.CriticRating;
|
||||
const tomatoLogo = document.createElement("img");
|
||||
tomatoLogo.className = "tomato-logo";
|
||||
const criticLogo = document.createElement("img");
|
||||
criticLogo.className = "critic-logo";
|
||||
tomatoLogo.src =
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Rotten_Tomatoes_positive_audience.svg/1920px-Rotten_Tomatoes_positive_audience.svg.png";
|
||||
let valueElement;
|
||||
if (typeof criticRating === "number") {
|
||||
valueElement = document.createTextNode(`${criticRating}% `);
|
||||
} else {
|
||||
valueElement = document.createTextNode(`N/A `);
|
||||
}
|
||||
if (criticRating === undefined || criticRating <= 59) {
|
||||
criticLogo.src =
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/5/52/Rotten_Tomatoes_rotten.svg/1024px-Rotten_Tomatoes_rotten.svg.png";
|
||||
criticLogo.alt = "Rotten Tomato";
|
||||
} else {
|
||||
criticLogo.src = "https://i.imgur.com/iMfwDk7.png";
|
||||
criticLogo.alt = "Fresh Tomato";
|
||||
}
|
||||
tomatoLogo.style.width = "15px";
|
||||
tomatoLogo.style.height = "17px";
|
||||
criticLogo.style.width = "15px";
|
||||
criticLogo.style.height = "15px";
|
||||
tomatoRatingDiv.appendChild(tomatoLogo);
|
||||
tomatoRatingDiv.appendChild(valueElement);
|
||||
tomatoRatingDiv.appendChild(criticLogo);
|
||||
tomatoRatingDiv.appendChild(createSeparator());
|
||||
const ageRatingDiv = document.createElement("div");
|
||||
ageRatingDiv.className = "age-rating";
|
||||
if (item.OfficialRating) {
|
||||
ageRatingDiv.innerHTML = `${item.OfficialRating}`;
|
||||
} else {
|
||||
ageRatingDiv.innerHTML = `N/A`;
|
||||
}
|
||||
const calender = "📅";
|
||||
const premiereDate = document.createElement("div");
|
||||
premiereDate.className = "date";
|
||||
const year = date ? new Date(date).getFullYear() : "N/A";
|
||||
premiereDate.textContent = isNaN(year) ? "N/A" : year;
|
||||
ratingTest.appendChild(tomatoRatingDiv);
|
||||
ratingTest.appendChild(document.createTextNode(calender));
|
||||
ratingTest.appendChild(premiereDate);
|
||||
ratingTest.appendChild(createSeparator());
|
||||
ratingTest.appendChild(ageRatingDiv);
|
||||
ratingTest.appendChild(createSeparator());
|
||||
ratingTest.appendChild(runTimeElement);
|
||||
const genresArray = item.Genres;
|
||||
function parseGenres(genresArray) {
|
||||
if (genresArray && genresArray.length > 0) {
|
||||
return genresArray.slice(0, 3).join(" 🔹 ");
|
||||
} else {
|
||||
return "No Genre Available";
|
||||
}
|
||||
}
|
||||
const genreElement = document.createElement("div");
|
||||
genreElement.className = "genre";
|
||||
genreElement.innerHTML = parseGenres(genresArray);
|
||||
const infoContainer = document.createElement("div");
|
||||
infoContainer.className = "info-container";
|
||||
infoContainer.appendChild(ratingTest);
|
||||
const playButton = document.createElement("button");
|
||||
playButton.className = "play-button";
|
||||
playButton.innerHTML = `
|
||||
<span class="play-icon"><i class="material-icons info_outline"></i></span>
|
||||
<span class="play-text">Details</span>
|
||||
`;
|
||||
playButton.onclick = () => {
|
||||
window.top.location.href = `/#!/details?id=${itemId}`;
|
||||
//window.location.href = `/Videos/${itemId}/stream.mp4?Static=true&mediaSourceId=${itemId}&deviceId=${deviceId}&api_key=${apiKey}`;
|
||||
//window.top.location.href = streamUrl;
|
||||
};
|
||||
slide.append(
|
||||
logoContainer,
|
||||
backdropContainer,
|
||||
gradientOverlay,
|
||||
featuredContent,
|
||||
plotContainer,
|
||||
infoContainer,
|
||||
genreElement,
|
||||
playButton
|
||||
);
|
||||
return slide;
|
||||
};
|
||||
const createSlideForItem = async (item, title) => {
|
||||
const container = document.getElementById("slides-container");
|
||||
const itemId = item.Id;
|
||||
const backdropUrl = `${window.location.origin}/Items/${itemId}/Images/Backdrop/0`;
|
||||
const logoUrl = `${window.location.origin}/Items/${itemId}/Images/Logo`;
|
||||
const [backdropExists, logoExists] = await Promise.all([
|
||||
fetch(backdropUrl, { method: "HEAD" }).then((res) => res.ok),
|
||||
fetch(logoUrl, { method: "HEAD" }).then((res) => res.ok),
|
||||
]);
|
||||
if (backdropExists && logoExists) {
|
||||
const slideElement = createSlideElement(item, title);
|
||||
container.appendChild(slideElement);
|
||||
console.log(`Added slide for item ${itemId}`);
|
||||
if (container.children.length === 1) {
|
||||
showSlide(0);
|
||||
}
|
||||
} else {
|
||||
console.warn(`Skipping item ${itemId}: Missing backdrop or logo.`);
|
||||
}
|
||||
};
|
||||
const fetchItemDetails = async (itemId) => {
|
||||
const response = await fetch(
|
||||
`${window.location.origin}/Users/${userId}/Items/${itemId}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `MediaBrowser Client="Jellyfin Web", Device="YourDeviceName", DeviceId="YourDeviceId", Version="YourClientVersion", Token="${token}"`,
|
||||
},
|
||||
}
|
||||
);
|
||||
const item = await response.json();
|
||||
console.log("Item Title:", item.Name);
|
||||
return item;
|
||||
};
|
||||
const fetchItemIdsFromList = async () => {
|
||||
try {
|
||||
const response = await fetch(listFileName);
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch list.txt");
|
||||
}
|
||||
const text = await response.text();
|
||||
return text
|
||||
.split("\n")
|
||||
.map((id) => id.trim())
|
||||
.filter((id) => id);
|
||||
} catch (error) {
|
||||
console.error("Error fetching list.txt:", error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
const fetchItemsFromServer = async () => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${window.location.origin}/Users/${userId}/Items?IncludeItemTypes=Movie,Series&Recursive=true&hasOverview=true&imageTypes=Logo,Backdrop&isPlayed=False&Limit=150`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `MediaBrowser Client="Jellyfin Web", Device="YourDeviceName", DeviceId="YourDeviceId", Version="YourClientVersion", Token="${token}"`,
|
||||
},
|
||||
}
|
||||
);
|
||||
const data = await response.json();
|
||||
const items = data.Items;
|
||||
const movies = items.filter((item) => item.Type === "Movie");
|
||||
const tvShows = items.filter((item) => item.Type === "Series");
|
||||
const shuffledMovies = shuffleArray(movies);
|
||||
const shuffledTvShows = shuffleArray(tvShows);
|
||||
const selectedMovies = shuffledMovies.slice(0, 15);
|
||||
const selectedTvShows = shuffledTvShows.slice(0, 15);
|
||||
const allItems = [];
|
||||
const maxLength = Math.max(selectedMovies.length, selectedTvShows.length);
|
||||
for (let i = 0; i < maxLength; i++) {
|
||||
if (i < selectedMovies.length) allItems.push(selectedMovies[i]);
|
||||
if (i < selectedTvShows.length) allItems.push(selectedTvShows[i]);
|
||||
}
|
||||
return allItems;
|
||||
} catch (error) {
|
||||
console.error("Error fetching items:", error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
const createSlidesForItems = async (items) => {
|
||||
await Promise.all(
|
||||
items.map((item) =>
|
||||
createSlideForItem(item, item.Type === "Movie" ? "Movie" : "TV Show")
|
||||
)
|
||||
);
|
||||
};
|
||||
const createPaginationDots = () => {
|
||||
const dotsContainer = document.createElement("div");
|
||||
dotsContainer.className = "dots-container";
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const dot = document.createElement("span");
|
||||
dot.className = "dot";
|
||||
dotsContainer.appendChild(dot);
|
||||
}
|
||||
const container = document.getElementById("slides-container");
|
||||
container.appendChild(dotsContainer);
|
||||
};
|
||||
const showSlide = (index) => {
|
||||
const slides = document.querySelectorAll(".slide");
|
||||
const dots = document.querySelectorAll(".dot");
|
||||
slides.forEach((slide, i) => {
|
||||
if (i === index) {
|
||||
slide.style.display = "block";
|
||||
slide.offsetHeight;
|
||||
slide.style.opacity = "1";
|
||||
slide.classList.add("active");
|
||||
} else {
|
||||
slide.style.opacity = "0";
|
||||
slide.classList.remove("active");
|
||||
setTimeout(() => {
|
||||
slide.style.display = "none";
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
dots.forEach((dot, i) => {
|
||||
dot.classList.toggle("active", i === index % 5);
|
||||
});
|
||||
};
|
||||
const initializeSlideshow = () => {
|
||||
const slides = document.querySelectorAll(".slide");
|
||||
createPaginationDots();
|
||||
const container = document.getElementById("slides-container");
|
||||
let currentSlideIndex = 0;
|
||||
let focusedSlide = null;
|
||||
let containerFocused = !1;
|
||||
const updateCurrentSlide = (index) => {
|
||||
if (isTransitioning) return; // Skip if already transitioning
|
||||
isTransitioning = true; // Set transitioning to true at the start
|
||||
currentSlideIndex = (index + slides.length) % slides.length;
|
||||
showSlide(currentSlideIndex);
|
||||
// Re-enable arrows after a short delay to prevent rapid clicking
|
||||
setTimeout(() => {
|
||||
isTransitioning = false; // Reset after transition completes
|
||||
}, 500); // Adjust the delay as needed (500ms is a reasonable starting point)
|
||||
};
|
||||
const openActiveSlide = () => {
|
||||
if (focusedSlide) {
|
||||
window.location.href = focusedSlide.href;
|
||||
}
|
||||
};
|
||||
if (slides.length > 0) {
|
||||
showSlide(currentSlideIndex);
|
||||
container.style.display = "block";
|
||||
setTimeout(() => {
|
||||
setInterval(() => {
|
||||
updateCurrentSlide(currentSlideIndex + 1);
|
||||
}, shuffleInterval);
|
||||
}, 8000);
|
||||
}
|
||||
slides.forEach((slide) => {
|
||||
slide.addEventListener(
|
||||
"focus",
|
||||
() => {
|
||||
focusedSlide = slide;
|
||||
container.classList.remove("disable-interaction");
|
||||
},
|
||||
!0
|
||||
);
|
||||
slide.addEventListener(
|
||||
"blur",
|
||||
() => {
|
||||
if (focusedSlide === slide) {
|
||||
focusedSlide = null;
|
||||
}
|
||||
},
|
||||
!0
|
||||
);
|
||||
});
|
||||
document.addEventListener("keydown", (event) => {
|
||||
if (containerFocused) {
|
||||
switch (event.keyCode) {
|
||||
case 37:
|
||||
updateCurrentSlide(currentSlideIndex - 1);
|
||||
break;
|
||||
case 39:
|
||||
updateCurrentSlide(currentSlideIndex + 1);
|
||||
break;
|
||||
case 13:
|
||||
case 32:
|
||||
openActiveSlide();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const leftArrow = document.createElement("div");
|
||||
const rightArrow = document.createElement("div");
|
||||
leftArrow.classList.add("arrow", "left-arrow");
|
||||
rightArrow.classList.add("arrow", "right-arrow");
|
||||
leftArrow.innerHTML = '<i class="material-icons arrow_back_ios_new"></i>';
|
||||
rightArrow.innerHTML = '<i class="material-icons arrow_forward_ios"></i>';
|
||||
container.appendChild(leftArrow);
|
||||
container.appendChild(rightArrow);
|
||||
leftArrow.addEventListener("click", () =>
|
||||
updateCurrentSlide(currentSlideIndex - 1)
|
||||
);
|
||||
rightArrow.addEventListener("click", () =>
|
||||
updateCurrentSlide(currentSlideIndex + 1)
|
||||
);
|
||||
container.addEventListener("focus", () => {
|
||||
containerFocused = !0;
|
||||
});
|
||||
container.addEventListener("blur", () => {
|
||||
containerFocused = !1;
|
||||
});
|
||||
};
|
||||
const initializeSlides = async () => {
|
||||
const itemIds = await fetchItemIdsFromList();
|
||||
let items;
|
||||
if (itemIds.length > 0) {
|
||||
const itemPromises = itemIds.map((id) => fetchItemDetails(id));
|
||||
items = await Promise.all(itemPromises);
|
||||
} else {
|
||||
const allItems = await fetchItemsFromServer();
|
||||
const itemPromises = allItems.map((item) => fetchItemDetails(item.Id));
|
||||
items = await Promise.all(itemPromises);
|
||||
}
|
||||
items = shuffleArray(items);
|
||||
await createSlidesForItems(items);
|
||||
initializeSlideshow();
|
||||
};
|
||||
initializeSlides();
|
||||
};
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
document.body.addEventListener("click", (event) => {
|
||||
const homeButton = event.target.matches(
|
||||
".headerHomeButton, .css-17c09up, .mainDrawer-scrollContainer > a:nth-child(2)"
|
||||
);
|
||||
if (homeButton) {
|
||||
event.preventDefault();
|
||||
window.location.href = "/web/index.html#/home.html";
|
||||
setTimeout(handleHomeNavigation, 300); // Delay for UI update
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user