Skip to content

Commit

Permalink
Update: Enhanced loading times (#192)
Browse files Browse the repository at this point in the history
  • Loading branch information
hoangsonww committed May 18, 2024
1 parent e8e3efd commit bf8bbee
Show file tree
Hide file tree
Showing 20 changed files with 291 additions and 539 deletions.
1 change: 0 additions & 1 deletion .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 3 additions & 4 deletions MovieVerse-Frontend/html/movie-details.html
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,6 @@ <h1 id="my-heading" style="margin-bottom: -10px" class="notranslate">

<div class="genres" id="genresDiv" style="margin-left: 25px; margin-top: 25px; display: none; height: 0">
<h2 id="search-title"></h2>
<button id="clear-search-btn" style="display: none;">Clear Search Results</button>
</div>

<main id="main" style="margin-left: 35px; height: 0"></main>
Expand All @@ -335,7 +334,7 @@ <h2 id="movie-title" class="movie-header"></h2>
❤️
</button>
</div>
<img id="movie-image" alt="Loading Movie Details..." style="width: 25vw; border-radius: 8px; z-index: 100002"/>
<img id="movie-image" alt="Loading Movie Details..." style="width: 25vw; border-radius: 8px; z-index: 100002" loading="lazy">
<h3>Your Rating:</h3>
<div class="rating" title="Click on a star to rate this movie!">
<span class="star" data-value="1" title="Oops, sorry to hear that this movie is disappointing to you">&#9733;</span>
Expand All @@ -348,8 +347,8 @@ <h3>Your Rating:</h3>
</div>

<!-- Right side for Description and Rating -->
<div class="movie-right" style="margin-top: -25px">
<p id="movie-description" class="movie-description" style="margin-top: -20px"></p>
<div class="movie-right" style="margin-top: -15px">
<p id="movie-description" class="movie-description" style="margin-top: -60px"></p>
<h2 id="movie-rating" class="movie-rating"></h2>
<div id="comments-section" style="margin-top: 75px">
<h3>Movie Comments</h3>
Expand Down
10 changes: 10 additions & 0 deletions MovieVerse-Frontend/html/tv-details.html
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,16 @@
bottom: 70px;
}
}

#movie-description {
margin-top: -129px;
}

@media (min-width: 767px) {
#movie-description {
margin-top: -60px;
}
}
</style>
</head>

Expand Down
142 changes: 13 additions & 129 deletions MovieVerse-Frontend/js/movie-details.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,108 +60,6 @@ function handleSearch() {
window.location.href = 'search.html';
}

function calculateMoviesToDisplay() {
const screenWidth = window.innerWidth;
if (screenWidth <= 689.9) return 10;
if (screenWidth <= 1021.24) return 20;
if (screenWidth <= 1353.74) return 21;
if (screenWidth <= 1684.9) return 20;
if (screenWidth <= 2017.49) return 20;
if (screenWidth <= 2349.99) return 18;
if (screenWidth <= 2681.99) return 21;
if (screenWidth <= 3014.49) return 24;
if (screenWidth <= 3345.99) return 27;
if (screenWidth <= 3677.99) return 20;
if (screenWidth <= 4009.99) return 22;
if (screenWidth <= 4340.99) return 24;
if (screenWidth <= 4673.49) return 26;
if (screenWidth <= 5005.99) return 28;
if (screenWidth <= 5337.99) return 30;
if (screenWidth <= 5669.99) return 32;
if (screenWidth <= 6001.99) return 34;
if (screenWidth <= 6333.99) return 36;
if (screenWidth <= 6665.99) return 38;
if (screenWidth <= 6997.99) return 40;
if (screenWidth <= 7329.99) return 42;
if (screenWidth <= 7661.99) return 44;
if (screenWidth <= 7993.99) return 46;
if (screenWidth <= 8325.99) return 48;
return 20;
}

async function getMovies(url) {
clearMovieDetails();
const numberOfMovies = calculateMoviesToDisplay();
const pagesToFetch = numberOfMovies <= 20 ? 1 : 2;
let allMovies = [];

for (let page = 1; page <= pagesToFetch; page++) {
const response = await fetch(`${url}&page=${page}`);
const data = await response.json();
allMovies = allMovies.concat(data.results);
}

const popularityThreshold = 0.5;

allMovies.sort((a, b) => {
const popularityDifference = Math.abs(a.popularity - b.popularity);
if (popularityDifference < popularityThreshold) {
return b.vote_average - a.vote_average;
}
return b.popularity - a.popularity;
});

if (allMovies.length > 0) {
showMovies(allMovies.slice(0, numberOfMovies));
document.getElementById('clear-search-btn').style.display = 'block';
}
else {
main.innerHTML = `<p>No movie with the specified search term found. Please try again.</p>`;
document.getElementById('clear-search-btn').style.display = 'none';
}
}

function clearMovieDetails() {
const movieDetailsContainer = document.getElementById('movie-details-container');
if (movieDetailsContainer) {
movieDetailsContainer.innerHTML = '';
}
}

function showMovies(movies){
main.innerHTML = '';
movies.forEach((movie) => {
const { id, poster_path, title, vote_average, overview } = movie;
const movieE1 = document.createElement('div');
const voteAverage = vote_average.toFixed(1);
movieE1.classList.add('movie');

const movieImage = poster_path
? `<img src="${IMGPATH + poster_path}" alt="${title}" style="cursor: pointer;" />`
: `<div class="no-image" style="text-align: center; padding: 20px;">Movie Image Not Available</div>`;

movieE1.innerHTML = `
${movieImage}
<div class="movie-info" style="cursor: pointer;">
<h3>${title}</h3>
<span class="${getClassByRate(vote_average)}">${voteAverage}</span>
</div>
<div class="overview" style="cursor: pointer;">
<h4>Movie Overview: </h4>
${overview}
</div>`;

movieE1.addEventListener('click', () => {
localStorage.setItem('selectedMovieId', id);
window.location.href = 'movie-details.html';
updateMovieVisitCount(id, title);
});

main.appendChild(movieE1);
});
applySettings();
}

async function ensureGenreMapIsAvailable() {
if (!localStorage.getItem('genreMap')) {
await fetchGenreMap();
Expand Down Expand Up @@ -417,6 +315,7 @@ function updateDirectorVisitCount(directorId, directorName) {
}

document.addEventListener('DOMContentLoaded', () => {
showSpinner();
initialMainContent = document.getElementById('main').innerHTML;

const movieId = localStorage.getItem('selectedMovieId');
Expand All @@ -427,11 +326,7 @@ document.addEventListener('DOMContentLoaded', () => {
fetchMovieDetails(1011985)
}

document.getElementById('clear-search-btn').style.display = 'none';
});

document.getElementById('clear-search-btn').addEventListener('click', () => {
location.reload();
hideSpinner();
});

function handleSignInOut() {
Expand Down Expand Up @@ -469,8 +364,10 @@ function updateSignInButtonState() {
}

document.addEventListener("DOMContentLoaded", function() {
showSpinner();
updateSignInButtonState();
document.getElementById('googleSignInBtn').addEventListener('click', handleSignInOut);
hideSpinner();
});

const twoLetterLangCodes = [
Expand Down Expand Up @@ -678,7 +575,6 @@ async function fetchMovieDetails(movieId) {
const code = `${getMovieCode()}`;
const url = `https://${getMovieVerseData()}/3/movie/${movieId}?${generateMovieNames()}${code}&append_to_response=credits,keywords,similar`;
const url2 = `https://${getMovieVerseData()}/3/movie/${movieId}?${generateMovieNames()}${code}&append_to_response=videos`;
const imdbUrl = `https://${getMovieVerseData()}/3/movie/${movieId}?${generateMovieNames()}${code}&append_to_response=external_ids`;

try {
const response = await fetch(url);
Expand Down Expand Up @@ -951,6 +847,7 @@ function getYouTubeVideoId(url) {
}

function positionTrailerButton() {
showSpinner();
if (!trailerButton)
return;

Expand All @@ -962,6 +859,7 @@ function positionTrailerButton() {
const movieRating = document.getElementById('movie-rating');
movieRating.parentNode.insertBefore(trailerButton, movieRating.nextSibling);
}
hideSpinner();
}

document.addEventListener('DOMContentLoaded', positionTrailerButton);
Expand Down Expand Up @@ -1042,12 +940,10 @@ async function fetchStreamingLinks(movieId) {
}

async function populateMovieDetails(movie, imdbRating, rtRating, metascore, awards, rated) {
document.getElementById('movie-image').src = `https://image.tmdb.org/t/p/w1280${movie.poster_path}`;
showSpinner();
document.getElementById('movie-title').textContent = movie.title;

const movieRating = movie.vote_average.toFixed(1);
const imdbLink = `https://www.imdb.com/title/${movie.imdb_id}`;

const streamingProviders = await fetchStreamingLinks(movie.id);
const movieTitleEncoded = encodeURIComponent(movie.title);

Expand Down Expand Up @@ -1084,15 +980,13 @@ async function populateMovieDetails(movie, imdbRating, rtRating, metascore, awar
}

return `<a href="${providerLink}" target="_blank" title="Watch on ${provider.provider_name}" style="display: inline-flex; align-items: flex-end; vertical-align: bottom;">
<img src="https://image.tmdb.org/t/p/original${provider.logo_path}" alt="${provider.provider_name}" style="width: 50px; margin-left: 10px;">
<img src="https://image.tmdb.org/t/p/original${provider.logo_path}" alt="${provider.provider_name}" style="width: 50px; margin-left: 10px;" loading="lazy">
</a>`;
}).join('') + `<a href="https://www.justwatch.com/us/search?q=${movieTitleEncoded}" target="_blank" title="View more streaming options on JustWatch" style="display: inline-flex; align-items: center; vertical-align: bottom; margin-left: 10px;">
<img src="../../images/justwatchlogo.webp" alt="JustWatch" style="width: 50px;">
<img src="../../images/justwatchlogo.webp" alt="JustWatch" style="width: 50px;" loading="lazy">
</a>` : 'No streaming options available.';

const rtLink = rtRating !== 'N/A' ? `https://www.rottentomatoes.com/m/${getRtSlug(movie.title)}` : '#';
const metaCriticsLink = metascore !== 'N/A' ? `https://www.metacritic.com/search/${createMetacriticSlug(movie.title)}` : '#';

const ratingDetails = getRatingDetails(rated);
const ratedElement = rated ? `<p id="movie-rated-element"><strong>Rated:</strong> <span style="color: ${ratingDetails.color};"><strong>${ratingDetails.text}</strong>${ratingDetails.description}</span></p>` : '';

Expand All @@ -1101,13 +995,13 @@ async function populateMovieDetails(movie, imdbRating, rtRating, metascore, awar

const movieImage = document.getElementById('movie-image');
const movieDescription = document.getElementById('movie-description');

const metascoreElement = metascore ? `<p><strong>Metascore:</strong> <a id="metacritics" href="${metaCriticsLink}" title="Click to search/view on Metacritics" target="_blank">${metascore}</a></p>` : '';
const awardsElement = awards ? `<p><strong>Awards:</strong> ${awards}</p>` : '';

if (movie.poster_path) {
movieImage.src = IMGPATH + movie.poster_path;
movieImage.alt = movie.title;
movieImage.loading = 'lazy';
}
else {
movieImage.style.display = 'none';
Expand All @@ -1118,7 +1012,6 @@ async function populateMovieDetails(movie, imdbRating, rtRating, metascore, awar
document.querySelector('.movie-left').appendChild(noImageText);
}

const fullLanguage = twoLetterLangCodes.find(lang => lang.code === movie.original_language).name;
const overview = movie.overview ? movie.overview : 'No overview available';
const genres = movie.genres.map(genre => genre.name).join(', ');
const releaseDate = movie.release_date ? movie.release_date : 'Release date not available';
Expand All @@ -1129,13 +1022,9 @@ async function populateMovieDetails(movie, imdbRating, rtRating, metascore, awar
const languages = movie.spoken_languages.map(lang => lang.name).join(', ');

const countries = movie.production_countries.map(country => country.name).join(', ');
const originalLanguage = fullLanguage ? fullLanguage : 'Language Info Not Available';
const popularityScore = movie.popularity.toFixed(0);
const status = movie.status ? movie.status : 'Status Info Not Available';

const voteCount = movie.vote_count.toLocaleString();
let keywords = movie.keywords ? movie.keywords.keywords.map(kw => kw.name).join(', ') : 'None Available';
const similarTitles = movie.similar ? movie.similar.results.map(m => m.title).join(', ') : 'None Available';
const scaledRating = (movie.vote_average / 2).toFixed(1);

if (keywords.length === 0) {
Expand All @@ -1146,18 +1035,12 @@ async function populateMovieDetails(movie, imdbRating, rtRating, metascore, awar
const isPopular = movie.popularity >= popularityThreshold;
const popularityText = isPopular ? `${popularityScore} (This movie is <strong>popular</strong>)` : `${popularityScore} (This movie is <strong>unpopular</strong>)`;

const adultContentIndicator = movie.adult
? `<span class="adult-indicator">Adult Content</span>`
: `<span class="general-indicator">General Audience</span>`;

const movieStatus = `<p><strong>Status:</strong> ${movie.status}</p>`;

const runtime = movie.runtime > 0
? movie.runtime + ' minutes'
: 'Runtime Info Not Available';

const originalTitle = movie.original_title !== movie.title ? `<p><strong>Original Title:</strong> ${movie.original_title}</p>` : `<p><strong>Original Title:</strong> ${movie.title}</p>`;

const tmdbRating = movie.vote_average.toFixed(1);

document.getElementById('movie-description').innerHTML += `
Expand Down Expand Up @@ -1317,14 +1200,15 @@ async function populateMovieDetails(movie, imdbRating, rtRating, metascore, awar
if (images.length > 0) {
imageElement.src = `https://image.tmdb.org/t/p/w1280${images[0].file_path}`;
}
imageElement.loading = 'lazy';
imageWrapper.appendChild(imageElement);
mediaContainer.appendChild(imageWrapper);

imageElement.addEventListener('click', function() {
const imageUrl = this.src;
const modalHtml = `
<div id="image-modal" style="z-index: 100022222; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.8); display: flex; justify-content: center; align-items: center;">
<img src="${imageUrl}" style="max-width: 80%; max-height: 80%; border-radius: 16px; cursor: default;" onclick="event.stopPropagation();">
<img src="${imageUrl}" style="max-width: 80%; max-height: 80%; border-radius: 16px; cursor: default;" onclick="event.stopPropagation();" loading="lazy" alt="Movie Image">
<span style="position: absolute; top: 10px; right: 25px; font-size: 40px; cursor: pointer" id="removeBtn">&times;</span>
</div>
`;
Expand Down Expand Up @@ -1405,7 +1289,7 @@ async function populateMovieDetails(movie, imdbRating, rtRating, metascore, awar
mediaContainer.innerHTML = '<p>No media available</p>';
}

applySettings();
hideSpinner();
}

function createImdbRatingCircle(imdbRating, imdbId) {
Expand Down
1 change: 1 addition & 0 deletions MovieVerse-Frontend/js/tv-details.js
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,7 @@ async function populateTvSeriesDetails(tvSeries, imdbRating) {
border-radius: 16px;
cursor: pointer;
`;
imageElement.loading = 'lazy';
mediaContainer.appendChild(imageElement);
}

Expand Down
Loading

0 comments on commit bf8bbee

Please sign in to comment.