Skip to content

Commit 538e31a

Browse files
authored
Merge pull request #206 from hoangsonww/main-deployment-branch
Main deployment branch
2 parents 66cedf8 + 8b909c1 commit 538e31a

File tree

226 files changed

+57667
-819
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

226 files changed

+57667
-819
lines changed

.github/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,13 @@ If you have a suggestion that would make this better, please fork the repo and c
134134
9. Visit the mobile app directory and install the dependencies (if any):
135135
```bash
136136
npm install
137-
cordova platform add ios
137+
cordova platform add swift
138138
cordova platform add android
139139
```
140140
10. Start the mobile app using Cordova (visit the `MovieVerse-Mobile` directory for more information):
141141
```bash
142142
cordova build
143-
cordova emulate ios
143+
cordova emulate swift
144144
cordova emulate android
145145
```
146146
11. Commit your Changes (Don't forget to create a branch for your feature):

MovieVerse-Frontend/js/movie-details.js

+2
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,8 @@ function createImdbRatingCircle(imdbRating, imdbId) {
16401640
imdbRating = 'N/A';
16411641
}
16421642

1643+
imdbRating = imdbRating.toFixed(1);
1644+
16431645
let circleContainer = document.getElementById('imdbRatingCircleContainer');
16441646
if (!circleContainer) {
16451647
circleContainer = document.createElement('div');

MovieVerse-Mobile/.idea/misc.xml

-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

MovieVerse-Mobile/README.md

+13-2
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ MovieVerse also offers a launch screen that welcomes users with a sleek and enga
6161
- [Apache Cordova](https://cordova.apache.org/) 10.0.0 or later
6262
- [Node.js](https://nodejs.org/en/) 14.17.0 or later
6363
- [npm](https://www.npmjs.com/) 6.14.13 or later
64+
- [Swift](https://developer.apple.com/swift/) 5.4.2 or later
65+
- [Java](https://www.oracle.com/java/technologies/javase-jdk11-downloads.html) 11.0.11 or later
66+
- [Gradle](https://gradle.org/) 7.0.2 or later
67+
- [Git](https://git-scm.com/) 2.32.0 or later
6468

6569
### Instructions
6670
1. **Clone the Repository**: Clone the repository to your local machine using the following command:
@@ -92,14 +96,21 @@ MovieVerse also offers a launch screen that welcomes users with a sleek and enga
9296
7. **Open the Project**: Open the project in Xcode and/or Android Studio to view the source code and test the app within the simulator.
9397
8. **Enjoy coding!**
9498

95-
**Important**: If you make any changes to the source code of the mobile app, you will need to update the iOS build process by removing iOS and adding it again using the following commands:
99+
**Important**: If you make any changes to the source code of the **iOS** mobile app, you will need to update the iOS build process by removing iOS and adding it again using the following commands:
96100

97101
```bash
98102
cordova platform rm ios
99103
cordova platform add ios
100104
```
101105

102-
The Android app, however, will build and run automatically as expected without any additional steps.
106+
Then, go to Xcode and re-build & re-run the app.
107+
108+
The **Android** app, however, will build and run automatically as expected without any additional steps. You will just have to re-build and re-run the app:
109+
110+
```bash
111+
cordova build android
112+
cordova emulate android
113+
```
103114

104115
## Usage
105116

MovieVerse-Mobile/app/js/about.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ async function rotateUserStats() {
242242
clearInterval(statRotationInterval);
243243
updateStatDisplay();
244244
statRotationInterval = setInterval(updateStatDisplay, 3000);
245+
localTimeDiv.scrollIntoView({ behavior: 'smooth' });
245246
});
246247
}
247248

@@ -328,4 +329,4 @@ function getMostCommonGenre() {
328329
return mostCommonGenre || 'Not Available';
329330
}
330331

331-
document.addEventListener('DOMContentLoaded', rotateUserStats);
332+
document.addEventListener('DOMContentLoaded', rotateUserStats);

MovieVerse-Mobile/app/js/actor-details.js

+163-30
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ const searchButton = document.getElementById("button-search");
33
const form = document.getElementById("form1");
44
const main = document.getElementById("main");
55
const IMGPATH = "https://image.tmdb.org/t/p/w1280";
6+
const IMGPATH2 = "https://image.tmdb.org/t/p/w185";
67
const searchTitle = document.getElementById("search-title");
8+
let currentIndex = sessionStorage.getItem('currentIndex') ? parseInt(sessionStorage.getItem('currentIndex')) : 0;
79

810
function showSpinner() {
911
document.getElementById('myModal').classList.add('modal-visible');
@@ -89,6 +91,7 @@ let initialMainContent = '';
8991

9092
document.addEventListener('DOMContentLoaded', () => {
9193
initialMainContent = document.getElementById('main').innerHTML;
94+
currentIndex = 0;
9295

9396
const actorId = localStorage.getItem('selectedActorId');
9497
if (actorId) {
@@ -97,8 +100,6 @@ document.addEventListener('DOMContentLoaded', () => {
97100
else {
98101
fetchActorDetails(2037);
99102
}
100-
101-
document.getElementById('clear-search-btn').style.display = 'none';
102103
});
103104

104105
async function fetchActorDetails(actorId) {
@@ -151,7 +152,6 @@ async function populateActorDetails(actor, credits) {
151152
const noImageText = document.createElement('h2');
152153
noImageText.textContent = 'Image Not Available';
153154
noImageText.style.textAlign = 'center';
154-
noImageText.style.height = '800px';
155155
document.querySelector('.actor-left').appendChild(noImageText);
156156
}
157157

@@ -193,19 +193,52 @@ async function populateActorDetails(actor, credits) {
193193

194194
const movieList = document.createElement('div');
195195
movieList.classList.add('movie-list');
196+
movieList.style.display = 'flex';
197+
movieList.style.flexWrap = 'wrap';
198+
movieList.style.justifyContent = 'center';
199+
movieList.style.gap = '5px';
200+
201+
let filmsToDisplay = credits.cast;
202+
filmsToDisplay = filmsToDisplay.sort((a, b) => b.popularity - a.popularity);
196203

197-
credits.cast.forEach((movie, index) => {
198-
const movieLink = document.createElement('span');
199-
movieLink.textContent = movie.title;
204+
filmsToDisplay.forEach((movie, index) => {
205+
const movieLink = document.createElement('a');
200206
movieLink.classList.add('movie-link');
201-
movieLink.addEventListener('click', () => {
202-
localStorage.setItem('selectedMovieId', movie.id);
203-
window.location.href = 'movie-details.html';
204-
});
207+
movieLink.href = 'javascript:void(0);';
208+
movieLink.setAttribute('onclick', `selectMovieId(${movie.id});`);
209+
210+
const movieItem = document.createElement('div');
211+
movieItem.classList.add('movie-item');
212+
213+
const movieImage = document.createElement('img');
214+
movieImage.classList.add('movie-image');
215+
216+
if (movie.poster_path) {
217+
movieImage.src = IMGPATH2 + movie.poster_path;
218+
movieImage.alt = `${movie.title} Poster`;
219+
} else {
220+
movieImage.alt = 'Image Not Available';
221+
movieImage.src = 'https://movie-verse.com/images/movie-default.jpg';
222+
movieImage.style.filter = 'grayscale(100%)';
223+
movieImage.style.objectFit = 'cover';
224+
}
225+
226+
movieItem.appendChild(movieImage);
227+
228+
const movieDetails = document.createElement('div');
229+
movieDetails.classList.add('movie-details');
230+
231+
const movieTitle = document.createElement('p');
232+
movieTitle.classList.add('movie-title');
233+
movieTitle.textContent = movie.title;
234+
movieDetails.appendChild(movieTitle);
235+
236+
movieItem.appendChild(movieDetails);
237+
movieLink.appendChild(movieItem);
205238
movieList.appendChild(movieLink);
206239

207240
if (index < credits.cast.length - 1) {
208-
movieList.appendChild(document.createTextNode(', '));
241+
movieList.appendChild(document.createTextNode(''));
209242
}
210243
});
211244

@@ -252,6 +285,20 @@ async function populateActorDetails(actor, credits) {
252285
detailsContainer.appendChild(mediaTitle);
253286
detailsContainer.appendChild(mediaContainer);
254287

288+
let imageWrapper = document.getElementById('image-wrapper');
289+
if (!imageWrapper) {
290+
imageWrapper = document.createElement('div');
291+
imageWrapper.id = 'image-wrapper';
292+
imageWrapper.style = `
293+
position: relative;
294+
display: flex;
295+
align-items: center;
296+
justify-content: center;
297+
width: 100%;
298+
`;
299+
mediaContainer.appendChild(imageWrapper);
300+
}
301+
255302
let imageElement = document.getElementById('series-media-image');
256303
if (!imageElement) {
257304
imageElement = document.createElement('img');
@@ -264,23 +311,29 @@ async function populateActorDetails(actor, credits) {
264311
border-radius: 16px;
265312
cursor: pointer;
266313
`;
267-
mediaContainer.appendChild(imageElement);
314+
imageElement.loading = 'lazy';
315+
imageWrapper.appendChild(imageElement);
268316
}
269317

270318
if (images.length > 0) {
271-
imageElement.src = `https://image.tmdb.org/t/p/w1280${images[0].file_path}`;
319+
imageElement.src = `https://image.tmdb.org/t/p/w780${images[0].file_path}`;
272320
}
273321

274-
imageElement.addEventListener('click', function() {
322+
imageElement.addEventListener('click', function () {
275323
const imageUrl = this.src;
324+
276325
const modalHtml = `
277-
<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;">
278-
<img src="${imageUrl}" style="max-width: 80%; max-height: 80%; border-radius: 10px; cursor: default;" onclick="event.stopPropagation();">
279-
<span style="position: absolute; top: 10px; right: 25px; font-size: 40px; cursor: pointer" id="removeBtn">&times;</span>
280-
</div>
281-
`;
326+
<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;">
327+
<button id="prevModalButton" style="position: absolute; left: 20px; top: 50%; transform: translateY(-50%); background-color: #7378c5; color: white; border-radius: 8px; height: 30px; width: 30px; border: none; cursor: pointer; z-index: 11;"><i class="fas fa-arrow-left"></i></button>
328+
<img src="${imageUrl}" style="max-width: 80%; max-height: 80%; border-radius: 10px; cursor: default; transition: opacity 0.5s ease-in-out;" onclick="event.stopPropagation();" alt="Media Image"/>
329+
<button id="nextModalButton" style="position: absolute; right: 20px; top: 50%; transform: translateY(-50%); background-color: #7378c5; color: white; border-radius: 8px; height: 30px; width: 30px; border: none; cursor: pointer; z-index: 11;"><i class="fas fa-arrow-right"></i></button>
330+
<span style="position: absolute; top: 10px; right: 25px; font-size: 40px; cursor: pointer" id="removeBtn">&times;</span>
331+
</div>
332+
`;
282333
document.body.insertAdjacentHTML('beforeend', modalHtml);
334+
283335
const modal = document.getElementById('image-modal');
336+
const modalImage = modal.querySelector('img');
284337
const closeModalBtn = document.getElementById('removeBtn');
285338

286339
closeModalBtn.onclick = function() {
@@ -292,8 +345,34 @@ async function populateActorDetails(actor, credits) {
292345
this.remove();
293346
}
294347
});
348+
349+
const prevModalButton = document.getElementById('prevModalButton');
350+
prevModalButton.onmouseover = () => prevModalButton.style.backgroundColor = '#ff8623';
351+
prevModalButton.onmouseout = () => prevModalButton.style.backgroundColor = '#7378c5';
352+
prevModalButton.onclick = () => navigateMediaAndModal(images, imageElement, modalImage, -1);
353+
354+
const nextModalButton = document.getElementById('nextModalButton');
355+
nextModalButton.onmouseover = () => nextModalButton.style.backgroundColor = '#ff8623';
356+
nextModalButton.onmouseout = () => nextModalButton.style.backgroundColor = '#7378c5';
357+
nextModalButton.onclick = () => navigateMediaAndModal(images, imageElement, modalImage, 1);
295358
});
296359

360+
function navigateMediaAndModal(images, imgElement1, imgElement2, direction) {
361+
imgElement1.style.opacity = '0';
362+
imgElement2.style.opacity = '0';
363+
currentIndex = (currentIndex + direction + images.length) % images.length;
364+
365+
setTimeout(() => {
366+
imgElement1.src = `https://image.tmdb.org/t/p/w780${images[currentIndex].file_path}`;
367+
imgElement2.src = `https://image.tmdb.org/t/p/w1280${images[currentIndex].file_path}`;
368+
imgElement1.style.opacity = '1';
369+
imgElement2.style.opacity = '1';
370+
}, 500);
371+
372+
sessionStorage.setItem('currentIndex', currentIndex);
373+
updateDots(currentIndex);
374+
}
375+
297376
let prevButton = document.getElementById('prev-media-button');
298377
let nextButton = document.getElementById('next-media-button');
299378
if (!prevButton || !nextButton) {
@@ -324,26 +403,74 @@ async function populateActorDetails(actor, credits) {
324403
prevButton.style.left = '0';
325404
nextButton.style.right = '0';
326405

327-
mediaContainer.appendChild(prevButton);
328-
mediaContainer.appendChild(nextButton);
406+
imageWrapper.appendChild(prevButton);
407+
imageWrapper.appendChild(nextButton);
329408
}
330409

331-
let currentIndex = 0;
332410
prevButton.onclick = () => navigateMedia(images, imageElement, -1);
333411
nextButton.onclick = () => navigateMedia(images, imageElement, 1);
334412

335413
function navigateMedia(images, imgElement, direction) {
336-
currentIndex += direction;
337-
if (currentIndex < 0) {
338-
currentIndex = images.length - 1;
339-
} else if (currentIndex >= images.length) {
340-
currentIndex = 0;
341-
}
342414
imgElement.style.opacity = '0';
415+
currentIndex = (currentIndex + direction + images.length) % images.length;
343416
setTimeout(() => {
344-
imgElement.src = `https://image.tmdb.org/t/p/w1280${images[currentIndex].file_path}`;
417+
imgElement.src = `https://image.tmdb.org/t/p/w780${images[currentIndex].file_path}`;
345418
imgElement.style.opacity = '1';
346-
}, 420);
419+
}, 500);
420+
421+
sessionStorage.setItem('currentIndex', currentIndex);
422+
updateDots(currentIndex);
423+
}
424+
425+
const indicatorContainer = document.createElement('div');
426+
indicatorContainer.style = `
427+
display: flex;
428+
flex-wrap: wrap;
429+
justify-content: center;
430+
margin-top: 15px;
431+
`;
432+
433+
const maxDotsPerLine = 10;
434+
let currentLine = document.createElement('div');
435+
currentLine.style.display = 'flex';
436+
437+
images.forEach((_, index) => {
438+
const dot = document.createElement('div');
439+
dot.className = 'indicator';
440+
dot.style = `
441+
width: 8px;
442+
height: 8px;
443+
margin: 0 5px;
444+
background-color: ${index === currentIndex ? '#ff8623' : '#bbb'};
445+
border-radius: 50%;
446+
cursor: pointer;
447+
margin-bottom: 5px;
448+
`;
449+
dot.addEventListener('click', () => {
450+
navigateMedia(images, imageElement, index - currentIndex);
451+
updateDots(index);
452+
});
453+
454+
currentLine.appendChild(dot);
455+
456+
if ((index + 1) % maxDotsPerLine === 0 && index !== images.length - 1) {
457+
indicatorContainer.appendChild(currentLine);
458+
currentLine = document.createElement('div');
459+
currentLine.style.display = 'flex';
460+
}
461+
});
462+
463+
if (currentLine.children.length > 0) {
464+
indicatorContainer.appendChild(currentLine);
465+
}
466+
467+
mediaContainer.appendChild(indicatorContainer);
468+
469+
function updateDots(newIndex) {
470+
const dots = document.querySelectorAll('.indicator');
471+
dots.forEach((dot, index) => {
472+
dot.style.backgroundColor = index === newIndex ? '#ff8623' : '#bbb';
473+
});
347474
}
348475

349476
if (window.innerWidth <= 767) {
@@ -357,6 +484,11 @@ async function populateActorDetails(actor, credits) {
357484
applySettings();
358485
}
359486

487+
function selectMovieId(movieId) {
488+
localStorage.setItem('selectedMovieId', movieId);
489+
window.location.href = 'movie-details.html';
490+
}
491+
360492
function calculateAge(birthday, deathday = null) {
361493
const birthDate = new Date(birthday);
362494
const referenceDate = deathday ? new Date(deathday) : new Date();
@@ -493,6 +625,7 @@ async function rotateUserStats() {
493625
clearInterval(statRotationInterval);
494626
updateStatDisplay();
495627
statRotationInterval = setInterval(updateStatDisplay, 3000);
628+
localTimeDiv.scrollIntoView({ behavior: 'smooth' });
496629
});
497630
}
498631

MovieVerse-Mobile/app/js/add-to-favorites.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -241,4 +241,4 @@ function updateMoviesFavorited(movieId) {
241241
favoritedMovies.push(movieId);
242242
localStorage.setItem('moviesFavorited', JSON.stringify(favoritedMovies));
243243
}
244-
}
244+
}

0 commit comments

Comments
 (0)