Created
December 30, 2025 01:45
-
-
Save wwtv127/cca402f04e382cdd4099d4b3bac2f8bc to your computer and use it in GitHub Desktop.
R1 Artifact: My Project
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> | |
| <title>R1 Tube</title> | |
| <style> | |
| :root { | |
| --r1-orange: #ff4e00; | |
| --bg-black: #0f0f0f; | |
| --text-white: #ffffff; | |
| --card-bg: #1a1a1a; | |
| --nav-height: 35px; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| -webkit-tap-highlight-color: transparent; | |
| } | |
| body { | |
| margin: 0; | |
| padding: 0; | |
| width: 240px; | |
| height: 287px; | |
| background: var(--bg-black); | |
| color: var(--text-white); | |
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; | |
| overflow: hidden; | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| /* Startup Screen */ | |
| #startup-screen { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 240px; | |
| height: 287px; | |
| background: #0f0f0f; | |
| z-index: 1000; | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| align-items: center; | |
| transition: opacity 0.5s ease; | |
| } | |
| #yt-loader-wrapper { | |
| width: 160px; | |
| height: 40px; | |
| position: relative; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| #yt-track { | |
| width: 140px; | |
| height: 2px; | |
| background: #2a2a2a; | |
| border-radius: 1px; | |
| position: relative; | |
| transition: opacity 0.3s ease; | |
| } | |
| #yt-progress { | |
| position: absolute; | |
| left: 0; | |
| top: 0; | |
| height: 100%; | |
| width: 0%; | |
| background: var(--r1-orange); | |
| border-radius: 1px; | |
| transition: width 1.8s cubic-bezier(0.1, 0.5, 0.1, 1); | |
| } | |
| #yt-progress::after { | |
| content: ''; | |
| position: absolute; | |
| right: -4px; | |
| top: -3px; | |
| width: 8px; | |
| height: 8px; | |
| background: white; | |
| border-radius: 50%; | |
| box-shadow: 0 0 8px var(--r1-orange); | |
| } | |
| #yt-logo-final { | |
| position: absolute; | |
| opacity: 0; | |
| transform: scale(0.9); | |
| transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.2); | |
| display: flex; | |
| align-items: center; | |
| gap: 6px; | |
| font-weight: 800; | |
| font-size: 20px; | |
| letter-spacing: -1px; | |
| color: white; | |
| pointer-events: none; | |
| } | |
| .r1-play-icon { | |
| width: 28px; | |
| height: 20px; | |
| background: var(--r1-orange); | |
| border-radius: 5px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| position: relative; | |
| flex-shrink: 0; | |
| } | |
| .r1-play-icon::after { | |
| content: ''; | |
| width: 0; | |
| height: 0; | |
| border-style: solid; | |
| border-width: 4px 0 4px 7px; | |
| border-color: transparent transparent transparent white; | |
| } | |
| #yt-logo-final span { color: var(--r1-orange); } | |
| /* Header */ | |
| #header { | |
| height: 40px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| padding: 0 10px; | |
| background: #0f0f0f; | |
| border-bottom: 1px solid #222; | |
| flex-shrink: 0; | |
| z-index: 10; | |
| } | |
| #logo { | |
| display: flex; | |
| align-items: center; | |
| gap: 4px; | |
| font-weight: 800; | |
| font-size: 14px; | |
| color: white; | |
| letter-spacing: -0.5px; | |
| } | |
| #logo .r1-play-icon { width: 20px; height: 14px; border-radius: 3px; } | |
| #logo .r1-play-icon::after { border-width: 3px 0 3px 5px; } | |
| #logo span { color: var(--r1-orange); } | |
| #search-btn { | |
| background: #222; | |
| border: 1px solid #444; | |
| color: white; | |
| padding: 4px 8px; | |
| border-radius: 4px; | |
| font-size: 10px; | |
| cursor: pointer; | |
| } | |
| /* Content Areas */ | |
| #content-area { | |
| flex-grow: 1; | |
| overflow-y: auto; | |
| scrollbar-width: none; | |
| position: relative; | |
| padding-bottom: var(--nav-height); | |
| } | |
| #content-area::-webkit-scrollbar { display: none; } | |
| /* Video Item Styling */ | |
| .video-item { | |
| display: flex; | |
| padding: 8px; | |
| border-bottom: 1px solid #1a1a1a; | |
| height: 70px; /* Fixed height for consistent calculation */ | |
| align-items: center; | |
| transition: opacity 0.2s ease, background 0.1s ease; | |
| opacity: 0; | |
| transform: translateY(10px); | |
| } | |
| .video-item.in-view { opacity: 1; transform: translateY(0); } | |
| .video-item.selected { background: #1a1a1a; border-left: 4px solid var(--r1-orange); } | |
| .thumbnail { width: 80px; height: 45px; background: #333; margin-right: 8px; border-radius: 4px; object-fit: cover; } | |
| .video-title { font-size: 11px; line-height: 1.2; height: 2.4em; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } | |
| /* Shorts Feed Styling */ | |
| #shorts-feed { | |
| display: none; | |
| height: 100%; | |
| overflow-y: scroll; | |
| scroll-snap-type: y mandatory; | |
| scrollbar-width: none; | |
| } | |
| #shorts-feed::-webkit-scrollbar { display: none; } | |
| .short-container { | |
| height: calc(287px - 40px - var(--nav-height)); | |
| width: 240px; | |
| scroll-snap-align: start; | |
| position: relative; | |
| background: #000; | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| align-items: center; | |
| overflow: hidden; | |
| } | |
| .short-placeholder { | |
| width: 100%; | |
| height: 100%; | |
| background: #000; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: #333; | |
| font-size: 10px; | |
| } | |
| .short-video-active { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| object-fit: cover; | |
| z-index: 2; | |
| } | |
| .short-info { | |
| position: absolute; | |
| bottom: 0; | |
| left: 0; | |
| right: 0; | |
| text-shadow: 0 1px 4px rgba(0,0,0,1); | |
| pointer-events: none; | |
| z-index: 5; | |
| background: linear-gradient(transparent, rgba(0,0,0,0.95)); | |
| padding: 12px 10px 8px 10px; | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: flex-end; | |
| } | |
| .short-title { | |
| font-size: 11px; | |
| font-weight: bold; | |
| margin-bottom: 2px; | |
| color: white; | |
| display: -webkit-box; | |
| -webkit-line-clamp: 2; | |
| -webkit-box-orient: vertical; | |
| overflow: hidden; | |
| } | |
| .short-channel { font-size: 9px; color: var(--r1-orange); font-weight: 600; } | |
| /* Navigation Bar */ | |
| #nav-bar { | |
| position: fixed; | |
| bottom: 0; | |
| left: 0; | |
| width: 240px; | |
| height: var(--nav-height); | |
| background: #000; | |
| display: flex; | |
| border-top: 1px solid #222; | |
| z-index: 50; | |
| } | |
| .nav-item { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 9px; | |
| color: #666; | |
| cursor: pointer; | |
| } | |
| .nav-item.active { color: var(--r1-orange); } | |
| .nav-icon { font-size: 14px; margin-bottom: 1px; } | |
| /* Overlays */ | |
| #player-overlay, #search-overlay { | |
| position: fixed; top: 0; left: 0; width: 240px; height: 287px; | |
| background: #000; display: none; z-index: 100; | |
| flex-direction: column; transform: translateY(100%); | |
| transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| #player-overlay.active, #search-overlay.active { display: flex; transform: translateY(0); } | |
| #video-container { width: 240px; height: 135px; background: #000; position: relative; } | |
| #back-btn { | |
| position: absolute; top: 8px; left: 8px; background: var(--r1-orange); | |
| color: white; border: none; padding: 4px 8px; border-radius: 4px; | |
| font-size: 10px; z-index: 110; cursor: pointer; | |
| } | |
| #video-details { padding: 8px 10px; flex-grow: 1; overflow-y: auto; font-size: 11px; background: #080808; } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="startup-screen"> | |
| <div id="yt-loader-wrapper"> | |
| <div id="yt-track"><div id="yt-progress"></div></div> | |
| <div id="yt-logo-final"> | |
| <div class="r1-play-icon"></div> | |
| R1<span>TUBE</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="header"> | |
| <div id="logo"> | |
| <div class="r1-play-icon"></div> | |
| R1<span>TUBE</span> | |
| </div> | |
| <button id="search-btn" onclick="openSearch()">🔍</button> | |
| </div> | |
| <div id="content-area"> | |
| <div id="video-list"></div> | |
| <div id="shorts-feed"></div> | |
| </div> | |
| <div id="nav-bar"> | |
| <div class="nav-item active" onclick="switchTab('home')"> | |
| <div class="nav-icon">🏠</div> | |
| Home | |
| </div> | |
| <div class="nav-item" onclick="switchTab('shorts')"> | |
| <div class="nav-icon">📱</div> | |
| Shorts | |
| </div> | |
| </div> | |
| <!-- Search Overlay --> | |
| <div id="search-overlay"> | |
| <div style="padding: 20px;"> | |
| <div style="margin-bottom: 10px; font-weight: bold; color: var(--r1-orange);">SEARCH</div> | |
| <input type="text" id="search-input" style="width:100%; background:#222; border:1px solid var(--r1-orange); color:white; padding:10px; border-radius:6px;" placeholder="Search YouTube..."> | |
| <div style="font-size: 10px; color: #666; margin-top: 10px;">Side Button to close.</div> | |
| </div> | |
| </div> | |
| <!-- Player Overlay --> | |
| <div id="player-overlay"> | |
| <div id="video-container"> | |
| <button id="back-btn" onclick="closePlayer()">BACK</button> | |
| </div> | |
| <div id="video-details"> | |
| <div id="det-title" style="font-weight:bold; color:white; margin-bottom:4px;"></div> | |
| <div id="det-likes" style="color:var(--r1-orange); font-size:10px; margin-bottom:8px;"></div> | |
| <div id="det-desc" style="color:#aaa; line-height:1.4;"></div> | |
| </div> | |
| </div> | |
| <script> | |
| const API_KEY = "AIzaSyBzB8j2OwAR6-PaIqWIijmZEdkw8gmFznQ"; | |
| let videos = []; | |
| let shorts = []; | |
| let currentIndex = 0; | |
| let currentShortIndex = -1; | |
| let currentTab = 'home'; | |
| let isPlayerOpen = false; | |
| let isSearchOpen = false; | |
| let nextShortsToken = ""; | |
| let shortsScrollTimeout = null; | |
| function initStartup() { | |
| const progress = document.getElementById('yt-progress'); | |
| const track = document.getElementById('yt-track'); | |
| const logo = document.getElementById('yt-logo-final'); | |
| const screen = document.getElementById('startup-screen'); | |
| setTimeout(() => { progress.style.width = '100%'; }, 100); | |
| setTimeout(() => { | |
| track.style.opacity = '0'; | |
| logo.style.opacity = '1'; | |
| logo.style.transform = 'scale(1)'; | |
| setTimeout(() => { | |
| screen.style.opacity = '0'; | |
| loadContent(); | |
| setTimeout(() => { screen.style.display = 'none'; }, 500); | |
| }, 1000); | |
| }, 1900); | |
| } | |
| async function loadContent() { | |
| searchVideos(); | |
| loadShorts(); | |
| } | |
| async function searchVideos(query = "popular now") { | |
| try { | |
| const ytResponse = await fetch(`https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=15&q=${encodeURIComponent(query)}&type=video&key=${API_KEY}`); | |
| const data = await ytResponse.json(); | |
| if (data.items) { | |
| videos = data.items.filter(v => v.id.videoId); | |
| renderHome(); | |
| } | |
| } catch (e) { console.error(e); } | |
| } | |
| async function loadShorts() { | |
| try { | |
| const response = await fetch(`https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=10&q=shorts&type=video&videoDuration=short&pageToken=${nextShortsToken}&key=${API_KEY}`); | |
| const data = await response.json(); | |
| if (data.items) { | |
| nextShortsToken = data.nextPageToken || ""; | |
| const newShorts = data.items.filter(v => v.id.videoId); | |
| shorts = [...shorts, ...newShorts]; | |
| renderShorts(); | |
| if (currentTab === 'shorts' && currentShortIndex === -1) { | |
| updateActiveShort(0); | |
| } | |
| } | |
| } catch (e) { console.error(e); } | |
| } | |
| function renderHome() { | |
| const list = document.getElementById('video-list'); | |
| list.innerHTML = ''; | |
| videos.forEach((vid, index) => { | |
| const item = document.createElement('div'); | |
| item.className = `video-item ${index === currentIndex ? 'selected' : ''}`; | |
| item.id = `video-item-${index}`; | |
| item.innerHTML = ` | |
| <img class="thumbnail" src="${vid.snippet.thumbnails.default.url}"> | |
| <div class="video-info"><div class="video-title">${vid.snippet.title}</div></div> | |
| `; | |
| item.onclick = () => { selectVideo(index); openPlayer(vid); }; | |
| list.appendChild(item); | |
| setTimeout(() => item.classList.add('in-view'), 50); | |
| }); | |
| } | |
| function selectVideo(index) { | |
| const listItems = document.querySelectorAll('.video-item'); | |
| listItems.forEach(item => item.classList.remove('selected')); | |
| currentIndex = index; | |
| const current = document.getElementById(`video-item-${index}`); | |
| if (current) { | |
| current.classList.add('selected'); | |
| // Manual Scroll Logic for Perfect Smoothness | |
| const container = document.getElementById('content-area'); | |
| const itemHeight = 70; // Matching CSS | |
| const targetScroll = index * itemHeight; | |
| container.scrollTo({ | |
| top: targetScroll, | |
| behavior: 'smooth' | |
| }); | |
| } | |
| } | |
| function renderShorts() { | |
| const feed = document.getElementById('shorts-feed'); | |
| const currentContainers = feed.querySelectorAll('.short-container').length; | |
| shorts.slice(currentContainers).forEach((short, index) => { | |
| const globalIndex = currentContainers + index; | |
| const container = document.createElement('div'); | |
| container.className = 'short-container'; | |
| container.id = `short-container-${globalIndex}`; | |
| container.innerHTML = ` | |
| <div class="short-placeholder">Loading...</div> | |
| <div class="short-info"> | |
| <div class="short-title">${short.snippet.title}</div> | |
| <div class="short-channel">@${short.snippet.channelTitle}</div> | |
| </div> | |
| `; | |
| feed.appendChild(container); | |
| }); | |
| } | |
| function updateActiveShort(index) { | |
| if (index === currentShortIndex || index < 0 || index >= shorts.length) return; | |
| const oldIframe = document.querySelector('.short-video-active'); | |
| if (oldIframe) oldIframe.remove(); | |
| currentShortIndex = index; | |
| const container = document.getElementById(`short-container-${index}`); | |
| if (!container) return; | |
| const videoId = shorts[index].id.videoId; | |
| const iframe = document.createElement('iframe'); | |
| iframe.className = 'short-video-active'; | |
| iframe.src = `https://www.youtube.com/embed/${videoId}?loop=1&playlist=${videoId}&autoplay=1&controls=0&modestbranding=1&rel=0&iv_load_policy=3`; | |
| iframe.frameBorder = "0"; | |
| iframe.allow = "autoplay; encrypted-media"; | |
| container.appendChild(iframe); | |
| } | |
| function switchTab(tab) { | |
| currentTab = tab; | |
| document.querySelectorAll('.nav-item').forEach(el => el.classList.remove('active')); | |
| document.getElementById('video-list').style.display = tab === 'home' ? 'block' : 'none'; | |
| document.getElementById('shorts-feed').style.display = tab === 'shorts' ? 'block' : 'none'; | |
| if (tab === 'home') { | |
| document.querySelectorAll('.nav-item')[0].classList.add('active'); | |
| const oldIframe = document.querySelector('.short-video-active'); | |
| if (oldIframe) oldIframe.remove(); | |
| currentShortIndex = -1; | |
| selectVideo(currentIndex); | |
| } else { | |
| document.querySelectorAll('.nav-item')[1].classList.add('active'); | |
| updateActiveShort(0); | |
| } | |
| } | |
| // Fixed Shorts Scroll Logic | |
| document.getElementById('shorts-feed').addEventListener('scroll', (e) => { | |
| if (shortsScrollTimeout) clearTimeout(shortsScrollTimeout); | |
| // Only update when scrolling stops to prevent jitter | |
| shortsScrollTimeout = setTimeout(() => { | |
| const el = e.target; | |
| const height = el.clientHeight; | |
| const newIndex = Math.round(el.scrollTop / height); | |
| if (newIndex !== currentShortIndex) { | |
| updateActiveShort(newIndex); | |
| } | |
| if (el.scrollHeight - el.scrollTop <= el.clientHeight + 100) { | |
| loadShorts(); | |
| } | |
| }, 150); // Small debounce window | |
| }); | |
| function openSearch() { | |
| isSearchOpen = true; | |
| const overlay = document.getElementById('search-overlay'); | |
| overlay.style.display = 'flex'; | |
| setTimeout(() => overlay.classList.add('active'), 10); | |
| document.getElementById('search-input').focus(); | |
| } | |
| function closeSearch() { | |
| document.getElementById('search-overlay').classList.remove('active'); | |
| setTimeout(() => { document.getElementById('search-overlay').style.display = 'none'; isSearchOpen = false; }, 300); | |
| } | |
| document.getElementById('search-input').addEventListener('keydown', (e) => { | |
| if (e.key === 'Enter') { | |
| searchVideos(e.target.value); | |
| closeSearch(); | |
| switchTab('home'); | |
| } | |
| }); | |
| async function openPlayer(video) { | |
| isPlayerOpen = true; | |
| const overlay = document.getElementById('player-overlay'); | |
| overlay.style.display = 'flex'; | |
| setTimeout(() => overlay.classList.add('active'), 10); | |
| document.getElementById('det-title').innerText = video.snippet.title; | |
| document.getElementById('det-likes').innerText = "Loading stats..."; | |
| document.getElementById('det-desc').innerText = video.snippet.description || "No description available."; | |
| try { | |
| const statsResponse = await fetch(`https://www.googleapis.com/youtube/v3/videos?part=statistics&id=${video.id.videoId}&key=${API_KEY}`); | |
| const statsData = await statsResponse.json(); | |
| if (statsData.items && statsData.items[0]) { | |
| const likes = parseInt(statsData.items[0].statistics.likeCount).toLocaleString(); | |
| const views = parseInt(statsData.items[0].statistics.viewCount).toLocaleString(); | |
| document.getElementById('det-likes').innerText = `👍 ${likes} Likes • 👁️ ${views} Views`; | |
| } | |
| } catch (e) { | |
| document.getElementById('det-likes').innerText = "Stats unavailable"; | |
| } | |
| const container = document.getElementById('video-container'); | |
| const old = container.querySelector('iframe'); if (old) old.remove(); | |
| const iframe = document.createElement('iframe'); | |
| iframe.width = "240"; iframe.height = "135"; | |
| iframe.src = `https://www.youtube.com/embed/${video.id.videoId}?autoplay=1`; | |
| iframe.frameBorder = "0"; iframe.allow = "autoplay; encrypted-media"; | |
| container.appendChild(iframe); | |
| } | |
| function closePlayer() { | |
| document.getElementById('player-overlay').classList.remove('active'); | |
| setTimeout(() => { | |
| document.getElementById('player-overlay').style.display = 'none'; | |
| const f = document.getElementById('video-container').querySelector('iframe'); | |
| if (f) f.remove(); | |
| isPlayerOpen = false; | |
| }, 300); | |
| } | |
| // Hardware Controls | |
| window.addEventListener("scrollUp", () => { | |
| if (currentTab === 'home' && !isPlayerOpen && !isSearchOpen) { | |
| if (currentIndex > 0) selectVideo(currentIndex - 1); | |
| } else if (currentTab === 'shorts') { | |
| document.getElementById('shorts-feed').scrollBy({ top: -212, behavior: 'smooth' }); | |
| } | |
| }); | |
| window.addEventListener("scrollDown", () => { | |
| if (currentTab === 'home' && !isPlayerOpen && !isSearchOpen) { | |
| if (currentIndex < videos.length - 1) selectVideo(currentIndex + 1); | |
| } else if (currentTab === 'shorts') { | |
| document.getElementById('shorts-feed').scrollBy({ top: 212, behavior: 'smooth' }); | |
| } | |
| }); | |
| window.addEventListener("sideClick", () => { | |
| if (isSearchOpen) closeSearch(); | |
| else if (isPlayerOpen) closePlayer(); | |
| else if (currentTab === 'home' && videos[currentIndex]) openPlayer(videos[currentIndex]); | |
| }); | |
| window.onload = initStartup; | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment