From 86651b50ef2eef16fb2e88909336a2615275deec Mon Sep 17 00:00:00 2001 From: NanamiAdmin Date: Fri, 13 Feb 2026 10:44:28 +0800 Subject: [PATCH] feat(video-page): add related videos section with shorts and regular videos - Add new related videos section with styling for shorts and regular videos - Implement logic to load and display related videos based on current video category - Restructure video page layout to accommodate new related videos section - Add shuffle functionality for video recommendations --- css/video.css | 187 +++++++++++++++++++++++++++++++++++++++++++++++--- js/video.js | 100 ++++++++++++++++++++++++++- video.html | 175 +++++++++++++++++++++++++--------------------- 3 files changed, 376 insertions(+), 86 deletions(-) diff --git a/css/video.css b/css/video.css index ec314c4..36da858 100644 --- a/css/video.css +++ b/css/video.css @@ -1,14 +1,21 @@ .video-content-wrapper { - flex: 1; display: flex; - flex-direction: column; - overflow-y: auto; + gap: 24px; padding: 24px; background-color: #121212; + flex: 1; + overflow: hidden; +} + +.video-main-section { + flex: 1; + display: flex; + flex-direction: column; + overflow-y: auto; } .video-player { - width: 70%; + width: 100%; aspect-ratio: 16 / 9; margin-bottom: 20px; border-radius: 20px; @@ -28,9 +35,11 @@ } .video-info-container { - margin-left: 30px; - margin-right: 30px; + width: 100%; margin-bottom: 20px; + padding: 1px; + border: 1px solid #000000; + box-sizing: border-box; } .video-title { @@ -255,9 +264,11 @@ } .comments-section { - margin-left: 30px; - margin-right: 30px; + width: 100%; margin-bottom: 40px; + padding: 1px; + border: 1px solid #000000; + box-sizing: border-box; } .comments-header { @@ -383,3 +394,163 @@ .comment-action-btn i { font-size: 16px; } + +.related-videos-section { + width: 400px; + display: flex; + flex-direction: column; + gap: 24px; + overflow-y: auto; + flex-shrink: 0; +} + +.section-title { + font-size: 16px; + font-weight: 600; + color: #ffffff; + margin: 0 0 12px 0; +} + +.shorts-section { + display: flex; + flex-direction: column; +} + +.shorts-list { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 12px; +} + +.short-item { + position: relative; + width: 100%; + padding-top: 177.78%; /* 9:16 ratio */ + background-color: #272727; + border-radius: 8px; + overflow: hidden; + cursor: pointer; + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.short-item:hover { + transform: translateY(-4px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); +} + +.short-thumbnail { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.short-thumbnail img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.short-info { + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding: 8px; + background: linear-gradient(to top, rgba(0, 0, 0, 0.8), transparent); +} + +.short-title { + font-size: 14px; + font-weight: 600; + color: #ffffff; + margin: 0 0 4px 0; + line-height: 1.4; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.short-channel { + font-size: 12px; + color: #aaaaaa; + margin: 0 0 2px 0; +} + +.short-views { + font-size: 12px; + color: #aaaaaa; + margin: 0; +} + +.regular-videos-section { + display: flex; + flex-direction: column; +} + +.regular-videos-list { + display: flex; + flex-direction: column; + gap: 12px; +} + +.regular-video-item { + display: flex; + gap: 12px; + cursor: pointer; + transition: background-color 0.2s; + border-radius: 12px; + padding: 8px; +} + +.regular-video-item:hover { + background-color: #272727; +} + +.regular-video-thumbnail { + width: 168px; + height: 94px; + border-radius: 8px; + overflow: hidden; + flex-shrink: 0; + background-color: #272727; +} + +.regular-video-thumbnail img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.regular-video-info { + flex: 1; + display: flex; + flex-direction: column; + justify-content: flex-start; +} + +.regular-video-title { + font-size: 14px; + font-weight: 600; + color: #ffffff; + margin: 0 0 6px 0; + line-height: 1.4; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.regular-video-channel { + font-size: 12px; + color: #aaaaaa; + margin: 0 0 4px 0; +} + +.regular-video-meta { + font-size: 12px; + color: #aaaaaa; + margin: 0; +} diff --git a/js/video.js b/js/video.js index 3902517..b2bdb22 100644 --- a/js/video.js +++ b/js/video.js @@ -1,15 +1,18 @@ let videoDetails = {}; let comments = []; +let allVideos = []; async function loadVideoData() { try { const response = await fetch('src/video.json'); const data = await response.json(); videoDetails = {}; + allVideos = data.videos; data.videos.forEach(video => { videoDetails[video.id] = video; }); comments = data.comments; + console.log('Video data loaded successfully:', allVideos.length, 'videos'); } catch (error) { console.error('Failed to load video data:', error); } @@ -17,12 +20,17 @@ async function loadVideoData() { function getVideoIdFromUrl() { const urlParams = new URLSearchParams(window.location.search); - return urlParams.get('id'); + const id = urlParams.get('id'); + return id ? parseInt(id) : 1; } function loadVideoInfo() { const videoId = getVideoIdFromUrl(); + console.log('Video ID:', videoId); + console.log('All videos:', allVideos.length); + const videoInfo = videoDetails[videoId]; + console.log('Video info:', videoInfo); if (videoInfo) { document.getElementById('videoTitle').textContent = videoInfo.title; @@ -39,11 +47,101 @@ function loadVideoInfo() { } document.title = videoInfo.title + ' - YouTube Revived'; + + loadRelatedVideos(videoInfo); } renderComments(); } +function loadRelatedVideos(currentVideo) { + console.log('Loading related videos for:', currentVideo.title); + console.log('Current category:', currentVideo.category); + + const currentCategory = currentVideo.category; + const currentId = currentVideo.id; + + const shortsList = document.getElementById('shortsList'); + const regularVideosList = document.getElementById('regularVideosList'); + + console.log('Shorts list element:', shortsList); + console.log('Regular videos list element:', regularVideosList); + + shortsList.innerHTML = ''; + regularVideosList.innerHTML = ''; + + const shorts = allVideos.filter(v => v.type === 'short' && v.id !== currentId); + const regularVideos = allVideos.filter(v => v.type === 'video' && v.id !== currentId); + + console.log('Found shorts:', shorts.length); + console.log('Found regular videos:', regularVideos.length); + + const sameCategoryShorts = shorts.filter(v => v.category === currentCategory); + const otherShorts = shorts.filter(v => v.category !== currentCategory); + + const sameCategoryRegularVideos = regularVideos.filter(v => v.category === currentCategory); + const otherRegularVideos = regularVideos.filter(v => v.category !== currentCategory); + + console.log('Same category shorts:', sameCategoryShorts.length); + console.log('Other shorts:', otherShorts.length); + console.log('Same category regular videos:', sameCategoryRegularVideos.length); + console.log('Other regular videos:', otherRegularVideos.length); + + shuffleArray(otherShorts); + shuffleArray(otherRegularVideos); + + const selectedShorts = [...sameCategoryShorts, ...otherShorts].slice(0, 3); + const selectedRegularVideos = [...sameCategoryRegularVideos, ...otherRegularVideos].slice(0, 10); + + console.log('Selected shorts:', selectedShorts.length); + console.log('Selected regular videos:', selectedRegularVideos.length); + + selectedShorts.forEach(short => { + const shortElement = document.createElement('div'); + shortElement.className = 'short-item'; + shortElement.innerHTML = ` +
+ ${short.title} +
+
+

${short.title}

+

${short.channel}

+

${short.views} views

+
+ `; + shortElement.addEventListener('click', () => { + window.location.href = `video.html?id=${short.id}`; + }); + shortsList.appendChild(shortElement); + }); + + selectedRegularVideos.forEach(video => { + const videoElement = document.createElement('div'); + videoElement.className = 'regular-video-item'; + videoElement.innerHTML = ` +
+ ${video.title} +
+
+

${video.title}

+

${video.channel}

+

${video.views} views • ${video.uploadDate}

+
+ `; + videoElement.addEventListener('click', () => { + window.location.href = `video.html?id=${video.id}`; + }); + regularVideosList.appendChild(videoElement); + }); +} + +function shuffleArray(array) { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } +} + function renderComments() { const commentsList = document.getElementById('commentsList'); const commentsCount = document.getElementById('commentsCount'); diff --git a/video.html b/video.html index 456a411..9050464 100644 --- a/video.html +++ b/video.html @@ -166,94 +166,115 @@
- -
- -
+
+ +
+ +
- -
-

Video Title

- -
-
-
+ +
+

Video Title

+ +
+
+
+
+ +
+
+
+
Channel Name
+
0 subscribers
+
+
+ +
+ +
+ + + + +
+ +
+
+ + Download +
+
+ + Report +
+
+
+
+ +
+ 0 views + 0 ago +
+ +
+
+ +
+

description

+
+
+ + +
+

+ 0 Comments +

+
+
-
-
Channel Name
-
0 subscribers
+
+
- -
- -
- - -
- 0 views - 0 ago -
- -
-
- -
-

description

- -
-

- 0 Comments -

-
-
- -
-
- + +