From b5c2c97559182e22e4db8342136e7adb29f057c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enes=20Yak=C4=B1=C5=9Ft=C4=B1r?= Date: Sun, 30 Aug 2026 02:21:21 +0300 Subject: [PATCH] feat(player): add pro player controls, speed adjustment, theater mode and quick info toast v1.4.0 --- client.js | 222 +++++++++++++++++++++++++++++++++++++++------------ package.json | 2 +- style.css | 75 +++++++++++++++++ 3 files changed, 249 insertions(+), 50 deletions(-) diff --git a/client.js b/client.js index 52a7cd0..657e1fb 100644 --- a/client.js +++ b/client.js @@ -576,13 +576,13 @@ setInterval(autoFixDOM, 1000); - // 3. Keyboard Shortcuts Modal + // 3. Keyboard Shortcuts Modal & Quick Info Engine (v1.4.0) function toggleShortcutsModal() { var modal = document.getElementById('yaktube-shortcuts-dialog'); if (modal) { if (modal.style.display === 'none' || !modal.style.display) { modal.style.display = 'flex'; - announce('Klavye kısayolları yardım penceresi açıldı. Kapatmak i�in Escape tuşuna basın.'); + announce('Klavye kısayolları yardım penceresi açıldı. Kapatmak için Escape tuşuna basın.'); var closeBtn = document.getElementById('yaktube-shortcuts-close'); if (closeBtn) closeBtn.focus(); } else { @@ -597,35 +597,43 @@ modal.setAttribute('aria-modal', 'true'); modal.setAttribute('aria-labelledby', 'yaktube-shortcuts-title'); modal.innerHTML = - '
' + - '

?? YakTube Klavye K�sayollar�

' + - '' + - '' + + '
' + + '
' + + '

⌨️ Video Oynatıcı & Gezinme Kısayolları

' + + '' + + '
' + + '
Kısayolİşlev
' + + '' + '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + '' + '
Kısayolİşlev
Space veya KOynat / Duraklat
Sol Ok veya J5 saniye geri sar
Sağ Ok veya L5 saniye ileri sar
Yukarı / Aşağı OkSesi %5 artır / azalt
MSesi Kapat / A� (Mute)
FTam Ekran
CAltyazıları A� / Kapat
/ (Bölü)Arama kutusuna hızlı git
0 - 9Videonun %0 - %90 noktasına atla
? (Shift+/)Bu yardım kılavuzunu aç / kapat
EscPencereleri kapat
Space veya KOynat / Duraklat
J / L10 saniye geri / ileri sar
Sol / Sağ Ok5 saniye geri / ileri sar
Yukarı / Aşağı OkSesi %5 artır / azalt
MSesi Kapat / Aç (Mute)
FTam Ekran
TSinema / Tiyatro Modu
CAltyazıları Aç / Kapat
IHızlı Video Bilgisi & İstatistikler
> / < (Shift+.)Oynatma hızını artır / azalt
0 - 9Videonun %0 - %90 noktasına atla
/Arama penceresini aç
Shift + VSesli aramayı başlat
' + - '' + '
'; document.body.appendChild(modal); - document.getElementById('yaktube-shortcuts-close').addEventListener('click', function () { - modal.style.display = 'none'; + var closeBtn = modal.querySelector('#yaktube-shortcuts-close'); + if (closeBtn) { + closeBtn.addEventListener('click', function () { + modal.style.display = 'none'; + }); + } + modal.addEventListener('click', function (e) { + if (e.target === modal) modal.style.display = 'none'; }); - var closeBtn = document.getElementById('yaktube-shortcuts-close'); - if (closeBtn) closeBtn.focus(); - announce('Klavye kısayolları yardım penceresi açıldı. Kapatmak i�in Escape tuşuna basın.'); + announce('Klavye kısayolları yardım penceresi açıldı. Kapatmak için Escape tuşuna basın.'); } } @@ -648,7 +656,77 @@ return mins + ' dakika ' + secs + ' saniye'; } - // 4. Global Keydown Listener + function showQuickVideoInfo() { + var video = getVideoElement(); + if (!video) { + announce('Şu anda aktif oynatılan bir video bulunmuyor.'); + return; + } + + var titleEl = document.querySelector('h1.video-title, .video-name, my-video-watch h1, .title'); + var title = titleEl ? titleEl.textContent.trim() : 'Video'; + var curTime = formatTime(video.currentTime); + var totalTime = formatTime(video.duration || 0); + var remaining = formatTime((video.duration || 0) - video.currentTime); + var speed = video.playbackRate + 'x'; + var volume = Math.round(video.volume * 100) + '%'; + var quality = video.videoHeight ? video.videoHeight + 'p' : 'Otomatik'; + + // Visual Toast + var existingToast = document.querySelector('.yaktube-video-info-toast'); + if (existingToast) existingToast.remove(); + + var toast = document.createElement('div'); + toast.className = 'yaktube-video-info-toast'; + toast.innerHTML = + '
📊 Video Bilgisi & Durum
' + + '
Başlık: ' + + (title.length > 28 ? title.substring(0, 28) + '...' : title) + + '
' + + '
Konum / Süre: ' + + curTime + + ' / ' + + totalTime + + '
' + + '
Kalan Süre: ' + + remaining + + '
' + + '
Çözünürlük: ' + + quality + + '
' + + '
Hız & Ses: ' + + speed + + ' | ' + + volume + + '
'; + + document.body.appendChild(toast); + setTimeout(function () { + if (toast.parentElement) toast.remove(); + }, 4000); + + announce( + 'Video Bilgisi: ' + + title + + '. Konum: ' + + curTime + + ', Toplam Süre: ' + + totalTime + + ', Kalan: ' + + remaining + + ', Oynatma Hızı: ' + + speed + + ', Ses: yüzde ' + + Math.round(video.volume * 100) + + ', Çözünürlük: ' + + quality, + true + ); + } + + var speedSteps = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]; + + // 4. Global Keydown Listener (Pro Video Player Engine) window.addEventListener('keydown', function (e) { if (e.key === 'Escape') { var shortcutsModal = document.getElementById('yaktube-shortcuts-dialog'); @@ -677,21 +755,6 @@ } } - if (e.key === '/' && !isInputFocused()) { - e.preventDefault(); - var searchInput = - document.querySelector('input[type="search"]') || - document.querySelector('input[name="search"]') || - document.querySelector('.search-input') || - document.querySelector('input'); - if (searchInput) { - searchInput.focus(); - if (searchInput.select) searchInput.select(); - announce('Arama kutusuna odaklanıldı.'); - } - return; - } - if (isInputFocused()) { return; } @@ -701,6 +764,7 @@ var key = e.key.toLowerCase(); + // Play / Pause (Space / K) if (key === ' ' || key === 'k') { e.preventDefault(); if (video.paused) { @@ -710,15 +774,29 @@ video.pause(); announce('Video duraklatıldı.'); } - } else if (key === 'j' || e.key === 'ArrowLeft') { + } + // Seek 10s Back / Forward (J / L) + else if (key === 'j') { + e.preventDefault(); + video.currentTime = Math.max(0, video.currentTime - 10); + announce('10 saniye geri sarıldı. Konum: ' + formatTime(video.currentTime)); + } else if (key === 'l') { + e.preventDefault(); + video.currentTime = Math.min(video.duration || 99999, video.currentTime + 10); + announce('10 saniye ileri sarıldı. Konum: ' + formatTime(video.currentTime)); + } + // Seek 5s Back / Forward (Left / Right Arrow) + else if (e.key === 'ArrowLeft') { e.preventDefault(); video.currentTime = Math.max(0, video.currentTime - 5); - announce('5 saniye geri sarıldı. Şu an: ' + formatTime(video.currentTime)); - } else if (key === 'l' || e.key === 'ArrowRight') { + announce('5 saniye geri sarıldı. Konum: ' + formatTime(video.currentTime)); + } else if (e.key === 'ArrowRight') { e.preventDefault(); video.currentTime = Math.min(video.duration || 99999, video.currentTime + 5); - announce('5 saniye ileri sarıldı. Şu an: ' + formatTime(video.currentTime)); - } else if (e.key === 'ArrowUp') { + announce('5 saniye ileri sarıldı. Konum: ' + formatTime(video.currentTime)); + } + // Volume Up / Down (Up / Down Arrow) + else if (e.key === 'ArrowUp') { e.preventDefault(); video.volume = Math.min(1, video.volume + 0.05); announce('Ses seviyesi yüzde ' + Math.round(video.volume * 100)); @@ -726,11 +804,15 @@ e.preventDefault(); video.volume = Math.max(0, video.volume - 0.05); announce('Ses seviyesi yüzde ' + Math.round(video.volume * 100)); - } else if (key === 'm') { + } + // Mute (M) + else if (key === 'm') { e.preventDefault(); video.muted = !video.muted; announce(video.muted ? 'Ses kapatıldı (Sessiz).' : 'Ses açıldı.'); - } else if (key === 'f') { + } + // Fullscreen (F) + else if (key === 'f') { e.preventDefault(); if (!document.fullscreenElement) { var container = video.closest('.video-js') || video.parentElement || video; @@ -740,7 +822,21 @@ if (document.exitFullscreen) document.exitFullscreen(); announce('Tam ekrandan çıkıldı.'); } - } else if (key === 'c') { + } + // Theater Mode (T) + else if (key === 't') { + e.preventDefault(); + document.body.classList.toggle('yaktube-theater-mode'); + var isTheater = document.body.classList.contains('yaktube-theater-mode'); + announce(isTheater ? 'Sinema modu açıldı.' : 'Sinema modundan çıkıldı.'); + } + // Quick Video Info (I) + else if (key === 'i') { + e.preventDefault(); + showQuickVideoInfo(); + } + // Subtitles (C) + else if (key === 'c') { e.preventDefault(); var tracks = video.textTracks; if (tracks && tracks.length > 0) { @@ -750,12 +846,40 @@ } else { announce('Bu videoda altyazı bulunmuyor.'); } - } else if (key >= '0' && key <= '9' && !e.ctrlKey && !e.altKey && !e.metaKey) { + } + // Speed Controls (< and > / Shift+, and Shift+.) + else if (e.key === '>' || (e.shiftKey && e.key === '.')) { + e.preventDefault(); + var curSpeed = video.playbackRate || 1; + var nextIdx = speedSteps.findIndex(function (s) { + return s > curSpeed; + }); + if (nextIdx !== -1) { + video.playbackRate = speedSteps[nextIdx]; + } else { + video.playbackRate = 2; + } + announce('Oynatma hızı ' + video.playbackRate + ' katına çıkarıldı.'); + } else if (e.key === '<' || (e.shiftKey && e.key === ',')) { + e.preventDefault(); + var curSpeed = video.playbackRate || 1; + var prevSteps = speedSteps.filter(function (s) { + return s < curSpeed; + }); + if (prevSteps.length > 0) { + video.playbackRate = prevSteps[prevSteps.length - 1]; + } else { + video.playbackRate = 0.25; + } + announce('Oynatma hızı ' + video.playbackRate + ' katına düşürüldü.'); + } + // Percentage Jumps (0 - 9) + else if (key >= '0' && key <= '9' && !e.ctrlKey && !e.altKey && !e.metaKey) { e.preventDefault(); var percent = parseInt(key, 10) * 10; if (video.duration) { video.currentTime = (video.duration * percent) / 100; - announce('Videonun yüzde ' + percent + ' noktasına atlandı. Şu an: ' + formatTime(video.currentTime)); + announce('Videonun yüzde ' + percent + ' noktasına atlandı. Konum: ' + formatTime(video.currentTime)); } } }); diff --git a/package.json b/package.json index d2f199b..e9f36ce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "peertube-plugin-yaktube-ondemand", - "version": "1.3.3", + "version": "1.4.0", "description": "Accessible On-Demand YouTube Import, Live Streams, Smart Recommendations and A11y Engine for PeerTube", "main": "main.js", "clientScripts": [ diff --git a/style.css b/style.css index b9c51c3..d09c933 100644 --- a/style.css +++ b/style.css @@ -768,3 +768,78 @@ my-search-typeahead, padding-top: 12px !important; margin-top: 8px !important; } + +/* -------------------------------------------------------------------------- */ +/* YOUTUBE THEATER MODE & QUICK VIDEO INFO TOAST (v1.4.0) */ +/* -------------------------------------------------------------------------- */ + +/* Theater / Cinema Mode (T) */ +body.yaktube-theater-mode my-video-watch, +body.yaktube-theater-mode .video-watch, +body.yaktube-theater-mode .watch-container { + max-width: 100% !important; + width: 100% !important; + padding: 0 !important; +} + +body.yaktube-theater-mode .player-container, +body.yaktube-theater-mode .video-player-container, +body.yaktube-theater-mode .player-wrapper { + max-height: 82vh !important; + height: 82vh !important; + width: 100% !important; + max-width: 100% !important; + background: #000 !important; + display: flex !important; + justify-content: center !important; + align-items: center !important; + margin-bottom: 20px !important; +} + +body.yaktube-theater-mode video, +body.yaktube-theater-mode .video-js { + width: 100% !important; + height: 100% !important; + max-height: 82vh !important; +} + +/* Quick Video Info Toast (I) */ +.yaktube-video-info-toast { + position: fixed !important; + top: 70px !important; + right: 20px !important; + background: rgba(20, 20, 26, 0.95) !important; + backdrop-filter: blur(12px) !important; + border: 1px solid rgba(255, 143, 55, 0.4) !important; + border-radius: 14px !important; + padding: 16px 20px !important; + color: #fff !important; + font-size: 14px !important; + z-index: 99999 !important; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.7) !important; + max-width: 380px !important; + animation: yaktube-fade-in 0.25s ease-out !important; + pointer-events: none !important; +} + +.yaktube-info-toast-title { + font-size: 15px !important; + font-weight: 700 !important; + color: #ff8f37 !important; + margin-bottom: 8px !important; + display: flex !important; + align-items: center !important; + gap: 6px !important; +} + +.yaktube-info-toast-row { + display: flex !important; + justify-content: space-between !important; + margin: 4px 0 !important; + font-size: 13px !important; + color: #ccc !important; +} + +.yaktube-info-toast-row b { + color: #fff !important; +}