Compare commits

...
5 Commits
4 changed files with 256 additions and 141 deletions
+231 -124
View File
@@ -57,7 +57,11 @@ try {
// Ensure Fediverse Global Search (SepiaSearch) is default in PeertubeServerConfig // Ensure Fediverse Global Search (SepiaSearch) is default in PeertubeServerConfig
try { try {
if (window.PeertubeServerConfig && window.PeertubeServerConfig.search && window.PeertubeServerConfig.search.searchIndex) { if (
window.PeertubeServerConfig &&
window.PeertubeServerConfig.search &&
window.PeertubeServerConfig.search.searchIndex
) {
window.PeertubeServerConfig.search.searchIndex.isDefaultSearch = true; window.PeertubeServerConfig.search.searchIndex.isDefaultSearch = true;
} }
} catch (e) {} } catch (e) {}
@@ -149,7 +153,7 @@ try {
) { ) {
var s = document.createElement('script'); var s = document.createElement('script');
s.id = 'yaknet-account-script'; s.id = 'yaknet-account-script';
s.src = 'https://auth.yakhub.com.tr/js/yaknet-account.js'; s.src = 'https://cdnjs.yakhub.com.tr/ajax/libs/yaknet-account/latest/yaknet-account.js';
s.async = true; s.async = true;
document.head.appendChild(s); document.head.appendChild(s);
} }
@@ -157,34 +161,37 @@ try {
// Intercept and sanitize YakNet Account Web Component popup menu // Intercept and sanitize YakNet Account Web Component popup menu
function hookYakNetAccountComponent() { function hookYakNetAccountComponent() {
if (typeof customElements === 'undefined') return; if (typeof customElements === 'undefined') return;
customElements.whenDefined('yaknet-account').then(function () { customElements
var YakNetAccount = customElements.get('yaknet-account'); .whenDefined('yaknet-account')
if (!YakNetAccount || !YakNetAccount.prototype || YakNetAccount.prototype._yaktubeSanitizerHooked) return; .then(function () {
YakNetAccount.prototype._yaktubeSanitizerHooked = true; var YakNetAccount = customElements.get('yaknet-account');
var originalRender = YakNetAccount.prototype.render; if (!YakNetAccount || !YakNetAccount.prototype || YakNetAccount.prototype._yaktubeSanitizerHooked) return;
if (typeof originalRender === 'function') { YakNetAccount.prototype._yaktubeSanitizerHooked = true;
YakNetAccount.prototype.render = function () { var originalRender = YakNetAccount.prototype.render;
originalRender.call(this); if (typeof originalRender === 'function') {
try { YakNetAccount.prototype.render = function () {
if (this.shadowRoot) { originalRender.call(this);
var isOfficial = isOfficialYakTubeServer(); try {
// 1. In YakTube: Suppress redundant/recursive link to YakTube inside services list if (this.shadowRoot) {
var selfLinks = this.shadowRoot.querySelectorAll('a[href*="yaktube.yakhub.com.tr"]'); var isOfficial = isOfficialYakTubeServer();
selfLinks.forEach(function (a) { // 1. In YakTube: Suppress redundant/recursive link to YakTube inside services list
a.style.display = 'none'; var selfLinks = this.shadowRoot.querySelectorAll('a[href*="yaktube.yakhub.com.tr"]');
}); selfLinks.forEach(function (a) {
// 2. In third-party PeerTube instances: Suppress entire external services grid & header to avoid community backlash a.style.display = 'none';
if (!isOfficial) { });
var appsGrid = this.shadowRoot.querySelector('.yn-apps-grid'); // 2. In third-party PeerTube instances: Suppress entire external services grid & header to avoid community backlash
if (appsGrid) appsGrid.style.display = 'none'; if (!isOfficial) {
var sectionTitle = this.shadowRoot.querySelector('#yn-services-label, .yn-section-title'); var appsGrid = this.shadowRoot.querySelector('.yn-apps-grid');
if (sectionTitle) sectionTitle.style.display = 'none'; if (appsGrid) appsGrid.style.display = 'none';
var sectionTitle = this.shadowRoot.querySelector('#yn-services-label, .yn-section-title');
if (sectionTitle) sectionTitle.style.display = 'none';
}
} }
} } catch (e) {}
} catch (e) {} };
}; }
} })
}).catch(function () {}); .catch(function () {});
} }
hookYakNetAccountComponent(); hookYakNetAccountComponent();
@@ -206,7 +213,7 @@ try {
if (!document.getElementById(iframeId)) { if (!document.getElementById(iframeId)) {
var iframe = document.createElement('iframe'); var iframe = document.createElement('iframe');
iframe.id = iframeId; iframe.id = iframeId;
iframe.src = 'https://auth.yakhub.com.tr/sdk/sso-frame'; iframe.src = 'https://developer-console.yakhub.com.tr/sdk/sso-frame';
iframe.title = 'YakNet Oturum Kontrolü'; iframe.title = 'YakNet Oturum Kontrolü';
iframe.setAttribute('aria-hidden', 'true'); iframe.setAttribute('aria-hidden', 'true');
iframe.tabIndex = -1; iframe.tabIndex = -1;
@@ -225,7 +232,7 @@ try {
sessionStorage.removeItem('yaknet_manual_logout'); sessionStorage.removeItem('yaknet_manual_logout');
var callbackUrl = 'https://yaktube.yakhub.com.tr/plugins/peertube-plugin-auth-yaknet/router/auth-callback'; var callbackUrl = 'https://yaktube.yakhub.com.tr/plugins/peertube-plugin-auth-yaknet/router/auth-callback';
window.location.href = window.location.href =
'https://auth.yakhub.com.tr/oauth/authorize?client_id=01a03c41-f758-721e-b927-619bffde5c23&redirect_uri=' + 'https://developer-console.yakhub.com.tr/oauth/authorize?client_id=01a03c41-f758-721e-b927-619bffde5c23&redirect_uri=' +
encodeURIComponent(callbackUrl) + encodeURIComponent(callbackUrl) +
'&response_type=code&scope='; '&response_type=code&scope=';
} }
@@ -255,7 +262,7 @@ try {
} }
}); });
// Global listener for YakNet SSO broadcast from auth.yakhub.com.tr // Global listener for YakNet SSO broadcast from developer-console.yakhub.com.tr
window.addEventListener('yaknet-auth', function (e) { window.addEventListener('yaknet-auth', function (e) {
if (e.detail && e.detail.authenticated && e.detail.user) { if (e.detail && e.detail.authenticated && e.detail.user) {
var token = localStorage.getItem('access_token'); var token = localStorage.getItem('access_token');
@@ -300,7 +307,8 @@ try {
sessionStorage.setItem('yaknet_manual_logout', 'true'); sessionStorage.setItem('yaknet_manual_logout', 'true');
} catch (err) {} } catch (err) {}
window.location.replace( window.location.replace(
'https://auth.yakhub.com.tr/sdk/logout?redirect_uri=' + encodeURIComponent('https://yaktube.yakhub.com.tr') 'https://developer-console.yakhub.com.tr/sdk/logout?redirect_uri=' +
encodeURIComponent('https://yaktube.yakhub.com.tr')
); );
} }
@@ -489,7 +497,7 @@ try {
'<yaknet-account ' + '<yaknet-account ' +
'client-id="01a03c41-f758-721e-b927-619bffde5c23" ' + 'client-id="01a03c41-f758-721e-b927-619bffde5c23" ' +
'redirect-uri="https://yaktube.yakhub.com.tr/plugins/peertube-plugin-auth-yaknet/router/auth-callback" ' + 'redirect-uri="https://yaktube.yakhub.com.tr/plugins/peertube-plugin-auth-yaknet/router/auth-callback" ' +
'base-url="https://auth.yakhub.com.tr" ' + 'base-url="https://developer-console.yakhub.com.tr" ' +
'login-url="/login" ' + 'login-url="/login" ' +
'authenticated="true" ' + 'authenticated="true" ' +
'user-name="' + 'user-name="' +
@@ -605,12 +613,12 @@ try {
'<p style="font-size: 13px; color: #94a3b8; margin-bottom: 16px; line-height: 1.45;">' + '<p style="font-size: 13px; color: #94a3b8; margin-bottom: 16px; line-height: 1.45;">' +
'YouTube gibi tek bir YakNet hesabıyla güvenle giriş yapabilir, kendi video ve müzik kanallarınızı oluşturabilirsiniz.' + 'YouTube gibi tek bir YakNet hesabıyla güvenle giriş yapabilir, kendi video ve müzik kanallarınızı oluşturabilirsiniz.' +
'</p>' + '</p>' +
'<a href="https://auth.yakhub.com.tr/oauth/authorize?client_id=01a03c41-f758-721e-b927-619bffde5c23&redirect_uri=https%3A%2F%2Fyaktube.yakhub.com.tr%2Fplugins%2Fpeertube-plugin-auth-yaknet%2Frouter%2Fauth-callback&response_type=code&scope=" class="yaknet-sso-login-btn" aria-label="YakNet Hesabınız ile Tek Tıkla Giriş Yapın">' + '<a href="https://developer-console.yakhub.com.tr/oauth/authorize?client_id=01a03c41-f758-721e-b927-619bffde5c23&redirect_uri=https%3A%2F%2Fyaktube.yakhub.com.tr%2Fplugins%2Fpeertube-plugin-auth-yaknet%2Frouter%2Fauth-callback&response_type=code&scope=" class="yaknet-sso-login-btn" aria-label="YakNet Hesabınız ile Tek Tıkla Giriş Yapın">' +
'<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><polyline points="10 17 15 12 10 7"/><line x1="15" y1="12" x2="3" y2="12"/></svg>' + '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><polyline points="10 17 15 12 10 7"/><line x1="15" y1="12" x2="3" y2="12"/></svg>' +
'<span>YakNet ile Giriş Yap</span>' + '<span>YakNet ile Giriş Yap</span>' +
'</a>' + '</a>' +
'<div style="margin-top: 14px; font-size: 13px; color: #94a3b8;">' + '<div style="margin-top: 14px; font-size: 13px; color: #94a3b8;">' +
'YakNet hesabınız yok mu? <a href="https://auth.yakhub.com.tr/register" target="_blank" rel="noopener noreferrer" style="color: #ff8f37; font-weight: 600; text-decoration: underline;">YakNet Hesabı Oluştur</a>' + 'YakNet hesabınız yok mu? <a href="https://developer-console.yakhub.com.tr/register" target="_blank" rel="noopener noreferrer" style="color: #ff8f37; font-weight: 600; text-decoration: underline;">YakNet Hesabı Oluştur</a>' +
'</div>' + '</div>' +
'<div style="margin-top: 14px; padding-top: 12px; border-top: 1px solid rgba(255,255,255,0.08); font-size: 11.5px; color: #64748b; line-height: 1.45;">' + '<div style="margin-top: 14px; padding-top: 12px; border-top: 1px solid rgba(255,255,255,0.08); font-size: 11.5px; color: #64748b; line-height: 1.45;">' +
'Giriş yaparak <a href="/about/instance" target="_blank" style="color: #94a3b8; text-decoration: underline;">Kullanım Koşulları</a>\'nı ve <a href="/about/instance" target="_blank" style="color: #94a3b8; text-decoration: underline;">Gizlilik Politikası</a>\'nı kabul etmiş sayılırsınız.' + 'Giriş yaparak <a href="/about/instance" target="_blank" style="color: #94a3b8; text-decoration: underline;">Kullanım Koşulları</a>\'nı ve <a href="/about/instance" target="_blank" style="color: #94a3b8; text-decoration: underline;">Gizlilik Politikası</a>\'nı kabul etmiş sayılırsınız.' +
@@ -630,8 +638,7 @@ try {
var registerLinks = document.querySelectorAll('a[href*="/signup"], a[href*="/register"]'); var registerLinks = document.querySelectorAll('a[href*="/signup"], a[href*="/register"]');
registerLinks.forEach(function (l) { registerLinks.forEach(function (l) {
l.href = 'https://auth.yakhub.com.tr/register'; l.href = 'https://developer-console.yakhub.com.tr/register';
l.target = '_blank';
l.innerText = 'YakNet Hesabı Oluştur'; l.innerText = 'YakNet Hesabı Oluştur';
}); });
@@ -1296,20 +1303,34 @@ try {
var header = document.createElement('div'); var header = document.createElement('div');
header.className = 'yaktube-feature-modal-header'; header.className = 'yaktube-feature-modal-header';
header.innerHTML = '<h3 class="yaktube-feature-modal-title"><span>⏱️</span> Uyku Zamanlayıcısı</h3>' + header.innerHTML =
'<h3 class="yaktube-feature-modal-title"><span>⏱️</span> Uyku Zamanlayıcısı</h3>' +
'<button class="yaktube-feature-modal-close" aria-label="Kapat (Escape)">&times;</button>'; '<button class="yaktube-feature-modal-close" aria-label="Kapat (Escape)">&times;</button>';
var body = document.createElement('div'); var body = document.createElement('div');
body.className = 'yaktube-feature-modal-body'; body.className = 'yaktube-feature-modal-body';
body.innerHTML = '<p class="yaktube-qr-desc">Videonun ne zaman durdurulacağını seçin. Süre bittiğinde ses yavaşça kısılarak oynatma durdurulur.</p>' + body.innerHTML =
'<p class="yaktube-qr-desc">Videonun ne zaman durdurulacağını seçin. Süre bittiğinde ses yavaşça kısılarak oynatma durdurulur.</p>' +
'<div class="yaktube-timer-options">' + '<div class="yaktube-timer-options">' +
'<button class="yaktube-timer-btn' + (sleepTimer.mode === '15' ? ' active' : '') + '" data-mins="15">15 Dakika</button>' + '<button class="yaktube-timer-btn' +
'<button class="yaktube-timer-btn' + (sleepTimer.mode === '30' ? ' active' : '') + '" data-mins="30">30 Dakika</button>' + (sleepTimer.mode === '15' ? ' active' : '') +
'<button class="yaktube-timer-btn' + (sleepTimer.mode === '45' ? ' active' : '') + '" data-mins="45">45 Dakika</button>' + '" data-mins="15">15 Dakika</button>' +
'<button class="yaktube-timer-btn' + (sleepTimer.mode === '60' ? ' active' : '') + '" data-mins="60">60 Dakika</button>' + '<button class="yaktube-timer-btn' +
(sleepTimer.mode === '30' ? ' active' : '') +
'" data-mins="30">30 Dakika</button>' +
'<button class="yaktube-timer-btn' +
(sleepTimer.mode === '45' ? ' active' : '') +
'" data-mins="45">45 Dakika</button>' +
'<button class="yaktube-timer-btn' +
(sleepTimer.mode === '60' ? ' active' : '') +
'" data-mins="60">60 Dakika</button>' +
'</div>' + '</div>' +
'<button class="yaktube-timer-btn' + (sleepTimer.mode === 'end' ? ' active' : '') + '" data-mins="end" style="width:100%;">🎬 Bu Video Bitince</button>' + '<button class="yaktube-timer-btn' +
(sleepTimer.targetTime || sleepTimer.mode ? '<button id="yaktube-timer-cancel-btn" class="yaktube-timer-btn" style="background:#ef4444!important;color:#fff!important;border-color:#ef4444!important;">❌ Zamanlayıcıyı İptal Et</button>' : ''); (sleepTimer.mode === 'end' ? ' active' : '') +
'" data-mins="end" style="width:100%;">🎬 Bu Video Bitince</button>' +
(sleepTimer.targetTime || sleepTimer.mode
? '<button id="yaktube-timer-cancel-btn" class="yaktube-timer-btn" style="background:#ef4444!important;color:#fff!important;border-color:#ef4444!important;">❌ Zamanlayıcıyı İptal Et</button>'
: '');
card.appendChild(header); card.appendChild(header);
card.appendChild(body); card.appendChild(body);
@@ -1376,18 +1397,24 @@ try {
var header = document.createElement('div'); var header = document.createElement('div');
header.className = 'yaktube-feature-modal-header'; header.className = 'yaktube-feature-modal-header';
header.innerHTML = '<h3 class="yaktube-feature-modal-title"><span>📱</span> Telefonda Devam Et</h3>' + header.innerHTML =
'<h3 class="yaktube-feature-modal-title"><span>📱</span> Telefonda Devam Et</h3>' +
'<button class="yaktube-feature-modal-close" aria-label="Kapat (Escape)">&times;</button>'; '<button class="yaktube-feature-modal-close" aria-label="Kapat (Escape)">&times;</button>';
var formattedTime = formatClockTime(currentSec); var formattedTime = formatClockTime(currentSec);
var qrImageUrl = 'https://api.qrserver.com/v1/create-qr-code/?size=220x220&margin=8&data=' + encodeURIComponent(targetUrl); var qrImageUrl =
'https://api.qrserver.com/v1/create-qr-code/?size=220x220&margin=8&data=' + encodeURIComponent(targetUrl);
var body = document.createElement('div'); var body = document.createElement('div');
body.className = 'yaktube-feature-modal-body'; body.className = 'yaktube-feature-modal-body';
body.innerHTML = body.innerHTML =
'<p class="yaktube-qr-desc">Telefonunuzun kamerasıyla QR kodu okutarak videoyu kaldığınız yerden (<strong>' + formattedTime + '</strong>) izlemeye devam edebilirsiniz.</p>' + '<p class="yaktube-qr-desc">Telefonunuzun kamerasıyla QR kodu okutarak videoyu kaldığınız yerden (<strong>' +
formattedTime +
'</strong>) izlemeye devam edebilirsiniz.</p>' +
'<div class="yaktube-qr-wrapper">' + '<div class="yaktube-qr-wrapper">' +
'<img src="' + qrImageUrl + '" alt="Video Bağlantısı QR Kodu" width="190" height="190" style="display:block;border-radius:8px;" />' + '<img src="' +
qrImageUrl +
'" alt="Video Bağlantısı QR Kodu" width="190" height="190" style="display:block;border-radius:8px;" />' +
'</div>' + '</div>' +
'<button id="yaktube-qr-copy-action-btn" class="yaktube-qr-copy-btn">📋 Bağlantıyı Kopyala</button>'; '<button id="yaktube-qr-copy-action-btn" class="yaktube-qr-copy-btn">📋 Bağlantıyı Kopyala</button>';
@@ -1409,15 +1436,18 @@ try {
var copyBtn = body.querySelector('#yaktube-qr-copy-action-btn'); var copyBtn = body.querySelector('#yaktube-qr-copy-action-btn');
copyBtn.addEventListener('click', function () { copyBtn.addEventListener('click', function () {
if (navigator.clipboard && navigator.clipboard.writeText) { if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(targetUrl).then(function () { navigator.clipboard
copyBtn.textContent = '✅ Bağlantı Kopyalandı!'; .writeText(targetUrl)
announce('Bağlantı panoya kopyalandı: ' + targetUrl); .then(function () {
setTimeout(function () { copyBtn.textContent = '✅ Bağlantı Kopyalandı!';
copyBtn.textContent = '📋 Bağlantıyı Kopyala'; announce('Bağlantı panoya kopyalandı: ' + targetUrl);
}, 2500); setTimeout(function () {
}).catch(function () { copyBtn.textContent = '📋 Bağlantıyı Kopyala';
fallbackCopy(targetUrl, copyBtn); }, 2500);
}); })
.catch(function () {
fallbackCopy(targetUrl, copyBtn);
});
} else { } else {
fallbackCopy(targetUrl, copyBtn); fallbackCopy(targetUrl, copyBtn);
} }
@@ -1454,7 +1484,8 @@ try {
if (!existing) { if (!existing) {
existing = document.createElement('div'); existing = document.createElement('div');
existing.className = 'yaktube-doubletap-overlay ' + className; existing.className = 'yaktube-doubletap-overlay ' + className;
existing.innerHTML = '<div class="yaktube-ripple-content">' + (isLeft ? '⏪ 10sn Geri' : '10sn İleri ⏩') + '</div>'; existing.innerHTML =
'<div class="yaktube-ripple-content">' + (isLeft ? '⏪ 10sn Geri' : '10sn İleri ⏩') + '</div>';
container.appendChild(existing); container.appendChild(existing);
} }
existing.classList.add('yaktube-ripple-active'); existing.classList.add('yaktube-ripple-active');
@@ -1466,7 +1497,8 @@ try {
function initTouchSeekGesture(video) { function initTouchSeekGesture(video) {
if (!video) return; if (!video) return;
var playerContainer = video.closest('.video-js, .player-container, .player, my-video-watch') || video.parentElement; var playerContainer =
video.closest('.video-js, .player-container, .player, my-video-watch') || video.parentElement;
if (!playerContainer || playerContainer.hasAttribute('data-yaktube-touch-seek-hooked')) return; if (!playerContainer || playerContainer.hasAttribute('data-yaktube-touch-seek-hooked')) return;
playerContainer.setAttribute('data-yaktube-touch-seek-hooked', 'true'); playerContainer.setAttribute('data-yaktube-touch-seek-hooked', 'true');
@@ -1543,7 +1575,8 @@ try {
} }
if (text === 'tam ekran' || text === 'büyük ekran' || text === 'tam ekran yap') { if (text === 'tam ekran' || text === 'büyük ekran' || text === 'tam ekran yap') {
var playerWrap = document.querySelector('.player-container, .video-player-container, my-video-watch .player') || video; var playerWrap =
document.querySelector('.player-container, .video-player-container, my-video-watch .player') || video;
if (playerWrap) { if (playerWrap) {
if (!document.fullscreenElement) { if (!document.fullscreenElement) {
if (playerWrap.requestFullscreen) playerWrap.requestFullscreen(); if (playerWrap.requestFullscreen) playerWrap.requestFullscreen();
@@ -1979,49 +2012,72 @@ try {
} }
function ensureFediverseBridge(query, currentSearchTarget) { function ensureFediverseBridge(query, currentSearchTarget) {
var searchMount = document.querySelector('my-search, my-search-results');
if (!searchMount) return;
var bridge = document.getElementById('yaktube-fediverse-bridge'); var bridge = document.getElementById('yaktube-fediverse-bridge');
var ondemandContainer = document.getElementById('yaktube-ondemand-container');
var searchResult = searchMount.querySelector('.search-result');
if (!bridge) { if (!bridge) {
bridge = document.createElement('div'); bridge = document.createElement('div');
bridge.id = 'yaktube-fediverse-bridge'; bridge.id = 'yaktube-fediverse-bridge';
bridge.className = 'yaktube-fediverse-bridge'; bridge.className = 'yaktube-fediverse-bridge';
bridge.setAttribute('role', 'region'); bridge.setAttribute('role', 'region');
bridge.setAttribute('aria-label', 'Fediverse Video Arama Ağı ve Kapsam Seçimi'); bridge.setAttribute('aria-label', 'Fediverse Video Arama Ağı ve Kapsam Seçimi');
}
var searchResult = document.querySelector('.search-result, my-search .search-result'); // Ensure bridge is always strictly inside searchMount
var ondemandContainer = document.getElementById('yaktube-ondemand-container'); if (ondemandContainer && ondemandContainer.parentElement === searchMount) {
if (ondemandContainer.nextSibling !== bridge) {
if (searchResult && searchResult.parentNode) { searchMount.insertBefore(bridge, ondemandContainer.nextSibling);
searchResult.parentNode.insertBefore(bridge, searchResult);
} else if (ondemandContainer && ondemandContainer.parentNode) {
ondemandContainer.parentNode.insertBefore(bridge, ondemandContainer.nextSibling);
} else {
var mainCol = document.querySelector('my-search, main, .main-col') || document.body;
mainCol.appendChild(bridge);
} }
} else if (searchResult && searchResult.parentElement === searchMount) {
if (bridge.nextSibling !== searchResult) {
searchMount.insertBefore(bridge, searchResult);
}
} else if (bridge.parentElement !== searchMount) {
searchMount.appendChild(bridge);
} }
var isFediverse = currentSearchTarget === 'search-index'; var isFediverse = currentSearchTarget === 'search-index';
bridge.innerHTML = bridge.innerHTML =
'<div class="yaktube-fediverse-bridge-content">' + '<div class="yaktube-fediverse-bridge-content">' +
'<div class="yaktube-fediverse-bridge-left">' + '<div class="yaktube-fediverse-bridge-left">' +
'<div class="yaktube-fediverse-bridge-badge-wrap">' + '<div class="yaktube-fediverse-bridge-badge-wrap">' +
'<span class="yaktube-fediverse-badge">🌐 Fediverse Ağı</span>' + '<span class="yaktube-fediverse-badge">🌐 Fediverse Ağı</span>' +
'<span class="yaktube-fediverse-status">' + '<span class="yaktube-fediverse-status">' +
(isFediverse ? 'SepiaSearch Küresel Fediverse Arama Aktif' : escapeHtml(getInstanceName()) + ' Yerel Arama Aktif') + (isFediverse
'</span>' + ? 'SepiaSearch Küresel Fediverse Arama Aktif'
'</div>' + : escapeHtml(getInstanceName()) + ' Yerel Arama Aktif') +
'<h2 class="yaktube-fediverse-title">🌐 Fediverse & Küresel Ağ Arama Sonuçları</h2>' + '</span>' +
'<p class="yaktube-fediverse-sub">Merkeziyetsiz federe ağdaki (SepiaSearch ve bağımsız PeerTube sunucuları) video sonuçları aşağıda listelenmektedir.</p>' + '</div>' +
'</div>' + '<h2 class="yaktube-fediverse-title">🌐 Fediverse & Küresel Ağ Arama Sonuçları</h2>' +
'<div class="yaktube-scope-selector" role="tablist" aria-label="Arama Kapsamı Seçimi">' + '<p class="yaktube-fediverse-sub">Merkeziyetsiz federe ağdaki (SepiaSearch ve bağımsız PeerTube sunucuları) video sonuçları aşağıda listelenmektedir.</p>' +
'<button type="button" id="yaktube-scope-global-btn" class="yaktube-scope-btn ' + (isFediverse ? 'active' : '') + '" role="tab" aria-selected="' + (isFediverse ? 'true' : 'false') + '" aria-label="Tüm Fediverse ve SepiaSearch ağındaki videoları ara" title="Tüm Fediverse genelinde ara">' + '</div>' +
'🌐 Tüm Fediverse (SepiaSearch)' + '<div class="yaktube-scope-selector" role="tablist" aria-label="Arama Kapsamı Seçimi">' +
'</button>' + '<button type="button" id="yaktube-scope-global-btn" class="yaktube-scope-btn ' +
'<button type="button" id="yaktube-scope-local-btn" class="yaktube-scope-btn ' + (!isFediverse ? 'active' : '') + '" role="tab" aria-selected="' + (!isFediverse ? 'true' : 'false') + '" aria-label="Sadece ' + escapeHtml(getInstanceName()) + ' yerel sunucusundaki videoları ara" title="Sadece ' + escapeHtml(getInstanceName()) + ' yerel kütüphanesinde ara">' + (isFediverse ? 'active' : '') +
'🏠 Sadece ' + escapeHtml(getInstanceName()) + ' (Yerel)' + '" role="tab" aria-selected="' +
'</button>' + (isFediverse ? 'true' : 'false') +
'</div>' + '" aria-label="Tüm Fediverse ve SepiaSearch ağındaki videoları ara" title="Tüm Fediverse genelinde ara">' +
'🌐 Tüm Fediverse (SepiaSearch)' +
'</button>' +
'<button type="button" id="yaktube-scope-local-btn" class="yaktube-scope-btn ' +
(!isFediverse ? 'active' : '') +
'" role="tab" aria-selected="' +
(!isFediverse ? 'true' : 'false') +
'" aria-label="Sadece ' +
escapeHtml(getInstanceName()) +
' yerel sunucusundaki videoları ara" title="Sadece ' +
escapeHtml(getInstanceName()) +
' yerel kütüphanesinde ara">' +
'🏠 Sadece ' +
escapeHtml(getInstanceName()) +
' (Yerel)' +
'</button>' +
'</div>' +
'</div>'; '</div>';
var globalBtn = document.getElementById('yaktube-scope-global-btn'); var globalBtn = document.getElementById('yaktube-scope-global-btn');
@@ -2150,8 +2206,8 @@ try {
'</div>' + '</div>' +
'</div>'; '</div>';
var mainMount = var mainMount = document.querySelector('my-search, my-search-results, .main-col .main-row, .main-col, main');
document.querySelector('my-search, my-search-results, router-outlet, main, .main-col') || document.body; if (!mainMount) mainMount = document.querySelector('.main-col');
if (mainMount && mainMount.firstChild) { if (mainMount && mainMount.firstChild) {
mainMount.insertBefore(liveContainer, mainMount.firstChild); mainMount.insertBefore(liveContainer, mainMount.firstChild);
} else if (mainMount) { } else if (mainMount) {
@@ -2442,6 +2498,14 @@ try {
var query = searchParam.trim(); var query = searchParam.trim();
// Clean up any stray containers mistakenly attached directly to document.body
try {
var strays = document.querySelectorAll('body > #yaktube-ondemand-container, body > #yaktube-fediverse-bridge');
strays.forEach(function (s) {
s.remove();
});
} catch (e) {}
// Ensure Fediverse Global Search (SepiaSearch) is default target if not specified in URL // Ensure Fediverse Global Search (SepiaSearch) is default target if not specified in URL
if (!url.searchParams.has('searchTarget')) { if (!url.searchParams.has('searchTarget')) {
url.searchParams.set('searchTarget', 'search-index'); url.searchParams.set('searchTarget', 'search-index');
@@ -2450,34 +2514,40 @@ try {
} }
var currentSearchTarget = url.searchParams.get('searchTarget') || 'search-index'; var currentSearchTarget = url.searchParams.get('searchTarget') || 'search-index';
// CRITICAL: We MUST wait for Angular to mount the search view (<my-search>)!
// If we inject before <my-search> exists, it lands in document.body before <my-app>,
// which pushes the entire site header, sidebar, and layout down the page.
var searchMount = document.querySelector('my-search, my-search-results');
if (!searchMount) {
return;
}
var queryKey = query + '___' + currentSearchTarget; var queryKey = query + '___' + currentSearchTarget;
var lastQueryKey = lastQuery + '___' + lastSearchTarget; var lastQueryKey = lastQuery + '___' + lastSearchTarget;
var container = document.getElementById('yaktube-ondemand-container');
var nativeResults = searchMount.querySelector('.search-result');
if (queryKey === lastQueryKey) { if (queryKey === lastQueryKey) {
var existingBridge = document.getElementById('yaktube-fediverse-bridge'); if (container && container.parentElement !== searchMount) {
if (!existingBridge && document.querySelector('my-search')) { searchMount.insertBefore(container, nativeResults || searchMount.firstChild);
ensureFediverseBridge(query, currentSearchTarget);
} }
ensureFediverseBridge(query, currentSearchTarget);
return; return;
} }
lastQuery = query; lastQuery = query;
lastSearchTarget = currentSearchTarget; lastSearchTarget = currentSearchTarget;
var container = document.getElementById('yaktube-ondemand-container');
if (!container) { if (!container) {
container = document.createElement('div'); container = document.createElement('div');
container.id = 'yaktube-ondemand-container'; container.id = 'yaktube-ondemand-container';
container.className = 'yaktube-ondemand-section'; container.className = 'yaktube-ondemand-section';
container.setAttribute('role', 'region'); container.setAttribute('role', 'region');
container.setAttribute('aria-label', 'Canlı YouTube ve ' + getInstanceName() + ' Arama Sonuçları'); container.setAttribute('aria-label', 'Canlı YouTube ve ' + getInstanceName() + ' Arama Sonuçları');
searchMount.insertBefore(container, nativeResults || searchMount.firstChild);
var mainContent = } else if (container.parentElement !== searchMount) {
document.querySelector('my-search, my-search-results, router-outlet, main, .main-col') || document.body; searchMount.insertBefore(container, nativeResults || searchMount.firstChild);
if (mainContent && mainContent.firstChild) {
mainContent.insertBefore(container, mainContent.firstChild);
} else if (mainContent) {
mainContent.appendChild(container);
}
} }
container.innerHTML = container.innerHTML =
@@ -2494,7 +2564,9 @@ try {
'</div>' + '</div>' +
'<div class="yaktube-loading">' + '<div class="yaktube-loading">' +
'<div class="yaktube-spinner" aria-hidden="true"></div>' + '<div class="yaktube-spinner" aria-hidden="true"></div>' +
'<div style="margin-top: 10px;">YouTube ve ' + escapeHtml(getInstanceName()) + ' yerel kütüphanesindeki eşleşmeler taranıyor...</div>' + '<div style="margin-top: 10px;">YouTube ve ' +
escapeHtml(getInstanceName()) +
' yerel kütüphanesindeki eşleşmeler taranıyor...</div>' +
'</div>'; '</div>';
var shortcutsBtn = document.getElementById('yaktube-open-shortcuts'); var shortcutsBtn = document.getElementById('yaktube-open-shortcuts');
@@ -2607,7 +2679,7 @@ try {
statusBadge = statusBadge =
'<span class="yaktube-badge" style="background: linear-gradient(135deg, #10b981 0%, #059669 100%); margin-bottom: 6px; display: inline-block;">✅ ' + '<span class="yaktube-badge" style="background: linear-gradient(135deg, #10b981 0%, #059669 100%); margin-bottom: 6px; display: inline-block;">✅ ' +
escapeHtml(getInstanceName()) + escapeHtml(getInstanceName()) +
'\'da Mevcut</span>'; "'da Mevcut</span>";
} }
var actionButton = ''; var actionButton = '';
@@ -2626,9 +2698,11 @@ try {
escapeHtml(item.localVideo.url) + escapeHtml(item.localVideo.url) +
'" class="yaktube-play-btn" aria-label="' + '" class="yaktube-play-btn" aria-label="' +
escapeHtml(item.title) + escapeHtml(item.title) +
' videosunu ' + escapeHtml(getInstanceName()) + '\'dan hemen izle">▶️ ' + ' videosunu ' +
escapeHtml(getInstanceName()) + escapeHtml(getInstanceName()) +
'\'dan İzle</a>'; '\'dan hemen izle">▶️ ' +
escapeHtml(getInstanceName()) +
"'dan İzle</a>";
} else { } else {
actionButton = actionButton =
'<button class="yaktube-import-btn" data-url="' + '<button class="yaktube-import-btn" data-url="' +
@@ -2641,10 +2715,10 @@ try {
escapeHtml(getInstanceName()) + escapeHtml(getInstanceName()) +
'\'a aktar ve izle">📥 ' + '\'a aktar ve izle">📥 ' +
escapeHtml(getInstanceName()) + escapeHtml(getInstanceName()) +
'\'a Aktar & İzle</button>'; "'a Aktar & İzle</button>";
} }
var durationText = isLive ? 'CANLI' : (item.durationFormatted || formatClockTime(item.duration)); var durationText = isLive ? 'CANLI' : item.durationFormatted || formatClockTime(item.duration);
var cardLabel = var cardLabel =
item.title + item.title +
(isLive ? ' (Canlı Yayın)' : isLocal ? ' (' + getInstanceName() + ' kütüphanenizde mevcut)' : '') + (isLive ? ' (Canlı Yayın)' : isLocal ? ' (' + getInstanceName() + ' kütüphanenizde mevcut)' : '') +
@@ -2705,20 +2779,34 @@ try {
if (localResults.length > 0) { if (localResults.length > 0) {
var localCardsHtml = ''; var localCardsHtml = '';
localResults.forEach(function (lItem) { localResults.forEach(function (lItem) {
var lThumb = lItem.thumbnailPath || (lItem.thumbnails && lItem.thumbnails[0] ? lItem.thumbnails[0].fileUrl : '/client/assets/images/default-thumbnail.jpg'); var lThumb =
lItem.thumbnailPath ||
(lItem.thumbnails && lItem.thumbnails[0]
? lItem.thumbnails[0].fileUrl
: '/client/assets/images/default-thumbnail.jpg');
var lDuration = formatClockTime(lItem.duration); var lDuration = formatClockTime(lItem.duration);
var lChannel = (lItem.channel && (lItem.channel.displayName || lItem.channel.name)) || var lChannel =
(lItem.account && (lItem.account.displayName || lItem.account.name)) || (lItem.channel && (lItem.channel.displayName || lItem.channel.name)) ||
getInstanceName(); (lItem.account && (lItem.account.displayName || lItem.account.name)) ||
var lWatchUrl = lItem.url || ('/videos/watch/' + (lItem.shortUUID || lItem.uuid)); getInstanceName();
var lWatchUrl = lItem.url || '/videos/watch/' + (lItem.shortUUID || lItem.uuid);
var lViews = (lItem.views || 0) + ' görüntüleme'; var lViews = (lItem.views || 0) + ' görüntüleme';
var lLabel = lItem.name + ', ' + lChannel + ', ' + getInstanceName() + ' yerel sunucusunda mevcut, Süre: ' + lDuration; var lLabel =
lItem.name +
', ' +
lChannel +
', ' +
getInstanceName() +
' yerel sunucusunda mevcut, Süre: ' +
lDuration;
localCardsHtml += localCardsHtml +=
'<div class="yaktube-card yaktube-local-card" role="article" tabindex="0" aria-label="' + '<div class="yaktube-card yaktube-local-card" role="article" tabindex="0" aria-label="' +
escapeHtml(lLabel) + escapeHtml(lLabel) +
'">' + '">' +
'<a href="' + escapeHtml(lWatchUrl) + '" style="text-decoration:none; color:inherit; display:flex; flex-direction:column; height:100%;">' + '<a href="' +
escapeHtml(lWatchUrl) +
'" style="text-decoration:none; color:inherit; display:flex; flex-direction:column; height:100%;">' +
'<div class="yaktube-thumb-wrap">' + '<div class="yaktube-thumb-wrap">' +
'<img class="yaktube-thumb-img" src="' + '<img class="yaktube-thumb-img" src="' +
escapeHtml(lThumb) + escapeHtml(lThumb) +
@@ -2731,30 +2819,42 @@ try {
'</div>' + '</div>' +
'<div class="yaktube-info">' + '<div class="yaktube-info">' +
'<div>' + '<div>' +
'<span class="yaktube-badge" style="background: linear-gradient(135deg, #10b981 0%, #059669 100%); margin-bottom: 6px; display: inline-block;">✅ ' + escapeHtml(getInstanceName()) + '\'da Mevcut</span>' + '<span class="yaktube-badge" style="background: linear-gradient(135deg, #10b981 0%, #059669 100%); margin-bottom: 6px; display: inline-block;">✅ ' +
escapeHtml(getInstanceName()) +
"'da Mevcut</span>" +
'<h3 class="yaktube-video-name" title="' + '<h3 class="yaktube-video-name" title="' +
escapeHtml(lItem.name) + escapeHtml(lItem.name) +
'" style="margin:0; font-size:13px; font-weight:600; line-height:1.35;">' + '" style="margin:0; font-size:13px; font-weight:600; line-height:1.35;">' +
escapeHtml(lItem.name) + escapeHtml(lItem.name) +
'</h3>' + '</h3>' +
'<div class="yaktube-channel-name">' + '<div class="yaktube-channel-name">' +
escapeHtml(lChannel) + ' • ' + escapeHtml(lViews) + escapeHtml(lChannel) +
' • ' +
escapeHtml(lViews) +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="yaktube-play-btn" style="margin-top:8px;">▶️ ' + escapeHtml(getInstanceName()) + '\'dan Hemen İzle</div>' + '<div class="yaktube-play-btn" style="margin-top:8px;">▶️ ' +
escapeHtml(getInstanceName()) +
"'dan Hemen İzle</div>" +
'</div>' + '</div>' +
'</a>' + '</a>' +
'</div>'; '</div>';
}); });
localShelfHtml = localShelfHtml =
'<div id="yaktube-local-shelf" class="yaktube-local-shelf" role="region" aria-label="' + escapeHtml(getInstanceName()) + ' Yerel Kütüphanesi">' + '<div id="yaktube-local-shelf" class="yaktube-local-shelf" role="region" aria-label="' +
escapeHtml(getInstanceName()) +
' Yerel Kütüphanesi">' +
'<div class="yaktube-header" style="margin-top: 24px; border-bottom-color: rgba(16, 185, 129, 0.3);">' + '<div class="yaktube-header" style="margin-top: 24px; border-bottom-color: rgba(16, 185, 129, 0.3);">' +
'<div class="yaktube-header-left">' + '<div class="yaktube-header-left">' +
'<span class="yaktube-badge" style="background: linear-gradient(135deg, #10b981 0%, #059669 100%);">✅ Yerel Kütüphane</span>' + '<span class="yaktube-badge" style="background: linear-gradient(135deg, #10b981 0%, #059669 100%);">✅ Yerel Kütüphane</span>' +
'<h2 class="yaktube-title-h3" style="margin:0; font-size:1.15rem;">"' + '<h2 class="yaktube-title-h3" style="margin:0; font-size:1.15rem;">"' +
escapeHtml(query) + escapeHtml(query) +
'" için ' + escapeHtml(getInstanceName()) + ' Sunucusunda ' + localTotal + ' Video Bulundu</h2>' + '" için ' +
escapeHtml(getInstanceName()) +
' Sunucusunda ' +
localTotal +
' Video Bulundu</h2>' +
'</div>' + '</div>' +
'<span class="yaktube-local-shelf-sub">Doğrudan sunucumuzda barındırılan, yüksek hızlı ve anında izlenebilen videolar</span>' + '<span class="yaktube-local-shelf-sub">Doğrudan sunucumuzda barındırılan, yüksek hızlı ve anında izlenebilen videolar</span>' +
'</div>' + '</div>' +
@@ -2895,7 +2995,7 @@ try {
if (email) headers['X-User-Email'] = email; if (email) headers['X-User-Email'] = email;
if (username) headers['X-User-Username'] = username; if (username) headers['X-User-Username'] = username;
var authUrl = 'https://auth.yakhub.com.tr/api/yaktube/search-history' + (queryParams || ''); var authUrl = 'https://developer-console.yakhub.com.tr/api/yaktube/search-history' + (queryParams || '');
var bridgeUrl = '/api-custom/search-history' + (queryParams || ''); var bridgeUrl = '/api-custom/search-history' + (queryParams || '');
var options = { var options = {
@@ -3350,7 +3450,8 @@ try {
announce('"' + transcript + '" için arama başlatılıyor...', true); announce('"' + transcript + '" için arama başlatılıyor...', true);
setTimeout(function () { setTimeout(function () {
closeFullSearchModal(); closeFullSearchModal();
window.location.href = '/search?search=' + encodeURIComponent(transcript) + '&searchTarget=search-index'; window.location.href =
'/search?search=' + encodeURIComponent(transcript) + '&searchTarget=search-index';
}, 500); }, 500);
} }
} }
@@ -4446,3 +4547,9 @@ try {
} catch (err) { } catch (err) {
console.error('[YakTube] Safe catch error:', err); console.error('[YakTube] Safe catch error:', err);
} }
export async function register(options) {
return true;
}
export { register as registerClient };
export default register;
+2 -8
View File
@@ -27,13 +27,7 @@ function resolveYtDlpPath(logger) {
path.join(process.cwd(), 'bin', 'yt-dlp.exe'), path.join(process.cwd(), 'bin', 'yt-dlp.exe'),
'yt-dlp.exe' 'yt-dlp.exe'
] ]
: [ : ['/usr/local/bin/yt-dlp', '/usr/bin/yt-dlp', '/bin/yt-dlp', path.join(process.cwd(), 'bin', 'yt-dlp'), 'yt-dlp'];
'/usr/local/bin/yt-dlp',
'/usr/bin/yt-dlp',
'/bin/yt-dlp',
path.join(process.cwd(), 'bin', 'yt-dlp'),
'yt-dlp'
];
for (const candidate of candidates) { for (const candidate of candidates) {
try { try {
@@ -64,7 +58,7 @@ async function getDefaultChannelId(category) {
return cachedChannels.defaultId || '1146'; return cachedChannels.defaultId || '1146';
} }
return new Promise((resolve) => { return new Promise(resolve => {
const req = http.request( const req = http.request(
{ {
hostname: '127.0.0.1', hostname: '127.0.0.1',
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "peertube-plugin-yaktube-ondemand", "name": "peertube-plugin-yaktube-ondemand",
"version": "1.5.0", "version": "1.5.3",
"description": "Accessible On-Demand YouTube Import, Live Streams, Smart Recommendations, Sleep Timer, Touch Gestures, Voice Assistant & A11y Engine for PeerTube", "description": "Accessible On-Demand YouTube Import, Live Streams, Smart Recommendations, Sleep Timer, Touch Gestures, Voice Assistant & A11y Engine for PeerTube",
"main": "main.js", "main": "main.js",
"library": "./main.js", "library": "./main.js",
@@ -43,7 +43,7 @@
"author": "Enes Yakıştır <[email protected]>", "author": "Enes Yakıştır <[email protected]>",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/yakistir98/peertube-plugin-yaktube-ondemand.git" "url": "git+https://github.com/yakistir98/peertube-plugin-yaktube-ondemand.git"
}, },
"homepage": "https://yaktube.yakhub.com.tr", "homepage": "https://yaktube.yakhub.com.tr",
"bugs": "https://github.com/yakistir98/peertube-plugin-yaktube-ondemand/issues", "bugs": "https://github.com/yakistir98/peertube-plugin-yaktube-ondemand/issues",
+21 -7
View File
@@ -1151,9 +1151,18 @@ body:has(#yaktube-ondemand-container) my-error-page {
} }
@keyframes yaktube-ripple-bounce { @keyframes yaktube-ripple-bounce {
0% { transform: scale(0.7); opacity: 0.5; } 0% {
50% { transform: scale(1.1); opacity: 1; } transform: scale(0.7);
100% { transform: scale(1); opacity: 1; } opacity: 0.5;
}
50% {
transform: scale(1.1);
opacity: 1;
}
100% {
transform: scale(1);
opacity: 1;
}
} }
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
@@ -1285,9 +1294,15 @@ body:has(#yaktube-ondemand-container) my-error-page {
} }
@keyframes yaktube-pulse { @keyframes yaktube-pulse {
0% { transform: scale(1); } 0% {
50% { transform: scale(1.04); } transform: scale(1);
100% { transform: scale(1); } }
50% {
transform: scale(1.04);
}
100% {
transform: scale(1);
}
} }
.yaktube-qr-wrapper { .yaktube-qr-wrapper {
@@ -1339,4 +1354,3 @@ body:has(#yaktube-ondemand-container) my-error-page {
box-shadow: 0 6px 20px rgba(255, 143, 55, 0.4) !important; box-shadow: 0 6px 20px rgba(255, 143, 55, 0.4) !important;
outline: none !important; outline: none !important;
} }