';
var formFirstChild = loginCard.firstElementChild;
if (formFirstChild) {
loginCard.insertBefore(ssoBox, formFirstChild);
} else {
loginCard.appendChild(ssoBox);
}
var registerLinks = document.querySelectorAll('a[href*="/signup"], a[href*="/register"]');
registerLinks.forEach(function (l) {
l.href = 'https://auth.yakhub.com.tr/register';
l.target = '_blank';
l.innerText = 'YakNet Hesabı Oluştur';
});
var formInputs = loginCard.querySelector('.form-group, .inputs, form') || loginCard.querySelector('input');
var containerToHide = formInputs ? formInputs.closest('form') || formInputs.parentElement : null;
if (containerToHide && !isLocalLogin) {
var subElements = Array.from(loginCard.children).filter(function (el) {
return (
el.id !== 'yaknet-login-section' && !el.classList.contains('title') && !el.classList.contains('page-title')
);
});
subElements.forEach(function (el) {
el.style.display = 'none';
});
var showAdminBtn = document.getElementById('yaktube-show-admin-login');
if (showAdminBtn) {
showAdminBtn.addEventListener('click', function (e) {
e.preventDefault();
subElements.forEach(function (el) {
el.style.display = '';
});
showAdminBtn.style.display = 'none';
announce('Yönetici kullanıcı adı ve şifre giriş formu açıldı.');
});
}
}
}
}
// 3. Intelligent Branding & A11y DOM Auto-Fixer
function autoFixDOM() {
injectAccessiblePlayerBar();
injectYakNetSSO();
// Aggressively remove generic Framasoft Open-in-App / Play Store banners
var genericAppBanners = document.querySelectorAll(
'my-open-app, my-client-app-banner, .open-app-container, .app-banner, [class*="open-app"], [class*="open-in-app"], .mobile-app-banner, my-open-in-app, .app-promotion, a[href*="play.google.com/store/apps/details?id=app.joinpeertube"], a[href*="f-droid.org"]'
);
genericAppBanners.forEach(function (banner) {
banner.setAttribute('aria-hidden', 'true');
banner.setAttribute('tabindex', '-1');
if (banner.parentElement) {
try {
banner.remove();
} catch (e) {
banner.style.display = 'none';
}
}
});
// Replace leftover PeerTube branding in visible UI texts
var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false);
var node;
while ((node = walker.nextNode())) {
var val = node.nodeValue;
if (val && (val.includes('PeerTube') || val.includes('Peertube'))) {
var parentTag = node.parentElement ? node.parentElement.tagName : '';
var parentElem = node.parentElement;
if (
parentElem &&
(parentElem.closest('#yaktube-ondemand-container') ||
parentElem.closest('#yaktube-live-watch-container') ||
parentElem.tagName === 'SCRIPT' ||
parentElem.tagName === 'STYLE')
) {
continue;
}
if (true) {
node.nodeValue = val
.replace(/PeerTube hakkında/gi, 'YakTube Hakkında')
.replace(/PeerTube'a katılın/gi, "YakTube'a Katılın")
.replace(/PeerTube örneği/gi, 'YakTube Sunucusu')
.replace(/PeerTube/g, 'YakTube');
}
}
}
// Semantic Headings (H3 for video titles, H2 for sections)
document
.querySelectorAll('.video-miniature, my-video-miniature, .video-card, .yaktube-card, [class*="miniature"]')
.forEach(function (card) {
var titleElement = card.querySelector(
'.video-miniature-name, .video-name, .yaktube-video-name, a[title], .title'
);
if (titleElement) {
if (!['H1', 'H2', 'H3', 'H4', 'H5', 'H6'].includes(titleElement.tagName)) {
titleElement.setAttribute('role', 'heading');
titleElement.setAttribute('aria-level', '3');
}
}
});
document
.querySelectorAll('.section-title, .sub-header, .videos-header, .page-header, .yaktube-title-h3')
.forEach(function (sec) {
if (!['H1', 'H2'].includes(sec.tagName)) {
sec.setAttribute('role', 'heading');
sec.setAttribute('aria-level', '2');
}
});
// Make native PeerTube comment authors accessible as H3 headings for screen readers
document
.querySelectorAll('my-video-comment, .video-comment, my-video-comment-thread, .comment, .comment-thread')
.forEach(function (commentEl) {
var authorEl = commentEl.querySelector(
'.display-name, .actor-name, .comment-author, a.actor-link, .video-comment-header-left a, .video-comment-header-left span'
);
if (
authorEl &&
!['H1', 'H2', 'H3', 'H4', 'H5', 'H6'].includes(authorEl.tagName) &&
!authorEl.getAttribute('role')
) {
authorEl.setAttribute('role', 'heading');
authorEl.setAttribute('aria-level', '3');
}
});
// Auto-fix unlabeled buttons
document.querySelectorAll('button:not([data-a11y-fixed])').forEach(function (btn) {
btn.setAttribute('data-a11y-fixed', 'true');
var text = (btn.textContent || '').trim();
var hasAria = btn.getAttribute('aria-label') || btn.getAttribute('title');
if (!text && !hasAria) {
var html = btn.innerHTML.toLowerCase();
var className = (btn.className || '').toLowerCase();
var icon = btn.querySelector('my-global-icon, i, svg, [class*="icon-"]');
var iconName = icon ? icon.className || icon.getAttribute('name') || '' : '';
if (html.includes('search') || className.includes('search') || iconName.includes('search')) {
btn.setAttribute('aria-label', 'Ara');
} else if (html.includes('bell') || className.includes('notification') || iconName.includes('bell')) {
btn.setAttribute('aria-label', 'Bildirimler');
} else if (html.includes('cog') || html.includes('setting') || className.includes('setting')) {
btn.setAttribute('aria-label', 'Ayarlar');
} else if (
html.includes('menu') ||
html.includes('bars') ||
className.includes('burger') ||
className.includes('menu')
) {
btn.setAttribute('aria-label', 'Ana Gezinme Menüsü');
} else if (html.includes('play') || className.includes('play')) {
btn.setAttribute('aria-label', 'Oynat');
} else if (html.includes('pause') || className.includes('pause')) {
btn.setAttribute('aria-label', 'Duraklat');
} else if (html.includes('volume') || html.includes('mute') || className.includes('volume')) {
btn.setAttribute('aria-label', 'Ses Kontrolü');
} else if (html.includes('fullscreen') || className.includes('fullscreen')) {
btn.setAttribute('aria-label', 'Tam Ekran');
} else if (
html.includes('ellipsis') ||
html.includes('more') ||
className.includes('more') ||
className.includes('action')
) {
btn.setAttribute('aria-label', 'Diğer İşlemler ve Seçenekler');
} else if (html.includes('trash') || html.includes('delete') || className.includes('delete')) {
btn.setAttribute('aria-label', 'Sil');
} else if (html.includes('edit') || className.includes('edit')) {
btn.setAttribute('aria-label', 'Düzenle');
} else if (html.includes('share') || className.includes('share')) {
btn.setAttribute('aria-label', 'Paylaş');
} else if (html.includes('thumb-up') || html.includes('like') || className.includes('like')) {
btn.setAttribute('aria-label', 'Beğen');
} else if (html.includes('thumb-down') || html.includes('dislike') || className.includes('dislike')) {
btn.setAttribute('aria-label', 'Beğenme');
} else if (html.includes('filter') || className.includes('filter')) {
btn.setAttribute('aria-label', 'Filtreler');
} else if (html.includes('close') || html.includes('times') || className.includes('close')) {
btn.setAttribute('aria-label', 'Kapat');
} else if (btn.closest('.vjs-control-bar')) {
btn.setAttribute('aria-label', 'Oynatıcı Düğmesi');
} else {
var parent = btn.parentElement;
if (parent && parent.title) {
btn.setAttribute('aria-label', parent.title);
} else {
btn.setAttribute('aria-label', 'Düğme');
}
}
}
});
// Auto-fix unlabeled images
document.querySelectorAll('img:not([data-a11y-fixed])').forEach(function (img) {
img.setAttribute('data-a11y-fixed', 'true');
var alt = img.getAttribute('alt');
if (!alt || alt.trim() === '') {
var card = img.closest('.video-miniature, .video-card, .yaktube-card, [class*="miniature"]');
if (card) {
var titleEl = card.querySelector('.video-miniature-name, .video-name, .yaktube-video-name, h3, h4, a[title]');
var titleText = titleEl ? (titleEl.textContent || titleEl.getAttribute('title') || '').trim() : '';
if (titleText) {
img.setAttribute('alt', titleText + ' video kapağı');
return;
}
}
var avatarContainer = img.closest('.actor-avatar, .channel-avatar, .avatar, [class*="avatar"]');
if (avatarContainer) {
var nameEl = avatarContainer.parentElement
? avatarContainer.parentElement.querySelector('.name, .actor-name, .channel-name')
: null;
var nameText = nameEl ? (nameEl.textContent || '').trim() : '';
img.setAttribute('alt', (nameText ? nameText + ' ' : '') + 'Profil Resmi');
return;
}
if (img.src && (img.src.includes('logo') || img.className.includes('logo'))) {
img.setAttribute('alt', getInstanceName() + ' Logo');
return;
}
var parentLink = img.closest('a');
if (parentLink && parentLink.textContent && parentLink.textContent.trim().length > 0) {
img.setAttribute('alt', '');
} else if (parentLink && parentLink.getAttribute('title')) {
img.setAttribute('alt', parentLink.getAttribute('title'));
} else {
img.setAttribute('alt', 'Görsel');
}
}
});
// Auto-fix unlabeled links
document.querySelectorAll('a:not([data-a11y-fixed])').forEach(function (a) {
a.setAttribute('data-a11y-fixed', 'true');
var text = (a.textContent || '').trim();
var hasAria = a.getAttribute('aria-label') || a.getAttribute('title');
if (!text && !hasAria) {
var img = a.querySelector('img');
if (img && img.alt) {
a.setAttribute('aria-label', img.alt);
} else if (a.href) {
if (a.href.includes('/videos/watch/')) {
a.setAttribute('aria-label', 'Videoyu İzle');
} else if (a.href.includes('/video-channels/')) {
a.setAttribute('aria-label', 'Kanal Sayfasına Git');
} else if (a.href.includes('/accounts/')) {
a.setAttribute('aria-label', 'Hesap Profiline Git');
} else if (a.href.includes('/videos/search')) {
a.setAttribute('aria-label', 'Arama Sayfası');
} else {
a.setAttribute('aria-label', 'Bağlantı');
}
}
}
});
// Auto-fix search inputs
document.querySelectorAll('input:not([data-a11y-fixed])').forEach(function (inp) {
inp.setAttribute('data-a11y-fixed', 'true');
if (!inp.getAttribute('aria-label') && !inp.getAttribute('placeholder') && !(inp.labels && inp.labels.length)) {
var type = (inp.getAttribute('type') || 'text').toLowerCase();
if (type === 'search') {
inp.setAttribute('aria-label', getInstanceName() + ' Video Arama');
} else if (type === 'checkbox') {
inp.setAttribute('aria-label', 'Seçim Kutusu');
} else if (type === 'password') {
inp.setAttribute('aria-label', 'Åifre');
}
}
});
}
setInterval(autoFixDOM, 1000);
// 3. Screen-Reader & Turkish Q Optimized Shortcuts & Player Bar (v1.4.1)
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.');
var closeBtn = document.getElementById('yaktube-shortcuts-close');
if (closeBtn) closeBtn.focus();
} else {
modal.style.display = 'none';
announce('Yardım penceresi kapatıldı.');
}
} else {
modal = document.createElement('div');
modal.id = 'yaktube-shortcuts-dialog';
modal.className = 'yaktube-modal-overlay';
modal.setAttribute('role', 'dialog');
modal.setAttribute('aria-modal', 'true');
modal.setAttribute('aria-labelledby', 'yaktube-shortcuts-title');
modal.innerHTML =
'
' +
'
' +
'
⌨️ Klavye Kısayolları (Ekran Okuyucu Uyumlu)
' +
'' +
'
' +
'
💡 Ekran Okuyucu Notu: Sanal imleç (Browse mode) açıkken kısayolları Alt tuşuyla birlikte kullanabilir veya video oynatıcı butonlarından faydalanabilirsiniz.
' +
'
' +
'
Kısayol (Evrensel / Tek Tuş)
İşlev
' +
'' +
'
Alt + K veya Space
Oynat / Duraklat
' +
'
Alt + J veya J
10 saniye geri sar
' +
'
Alt + L veya L
10 saniye ileri sar
' +
'
Alt + Yukarı / Aşağı
Sesi %5 artır / azalt
' +
'
Alt + M veya M
Sesi Kapat / Aç (Mute)
' +
'
Alt + T veya T
Sinema / Tiyatro Modu
' +
'
Alt + I veya I
Hızlı Video Bilgisi & İstatistikler
' +
'
Alt + C veya C
Altyazıları Aç / Kapat
' +
'
Alt + . / Alt + ,
Oynatma hızını artır / azalt
' +
'
Alt + S veya / (Shift+7)
Arama penceresini aç
' +
'
Alt + V veya Shift + V
Sesli aramayı başlat
' +
'
Alt + H veya F1 veya ?
Bu kılavuzu aç / kapat
' +
'' +
'
' +
'
';
document.body.appendChild(modal);
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';
});
announce('Klavye kısayolları yardım penceresi açıldı. Kapatmak için Escape tuşuna basın.');
}
}
function isInputFocused() {
var el = document.activeElement;
if (!el) return false;
var tag = el.tagName ? el.tagName.toUpperCase() : '';
return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || el.isContentEditable;
}
function getVideoElement() {
return document.querySelector('video');
}
function formatTime(seconds) {
if (isNaN(seconds) || seconds < 0) return '0 saniye';
var mins = Math.floor(seconds / 60);
var secs = Math.floor(seconds % 60);
if (mins === 0) return secs + ' saniye';
return mins + ' dakika ' + secs + ' saniye';
}
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 || 1) + 'x';
var volume = Math.round((video.volume || 1) * 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 =
'
YouTube ve Fediverse\'deki en alakalı videolar getiriliyor...
' +
'
';
announce(searchQuery + ' için ilgili video önerileri yükleniyor.');
fetch('/api-custom/youtube-search?q=' + encodeURIComponent(searchQuery))
.then(function (res) {
return res.json();
})
.then(function (data) {
var rawResults = data.results || [];
var normalizedCurrentTitle = rawTitle.toLowerCase().trim();
var uniqueResults = [];
var seenIds = {};
rawResults.forEach(function (item) {
if (item && item.id && !seenIds[item.id] && item.title) {
var itemTitle = item.title.toLowerCase().trim();
if (itemTitle !== normalizedCurrentTitle && !itemTitle.includes(normalizedCurrentTitle)) {
seenIds[item.id] = true;
uniqueResults.push(item);
}
}
});
cachedRelatedResults = uniqueResults;
cachedRelatedQuery = searchQuery;
currentActiveVideoKey = thisVideoKey;
relatedShowAll = false;
renderRelatedCards(container, uniqueResults, searchQuery);
var initialCount = Math.min(uniqueResults.length, 12);
if (uniqueResults.length === 0) {
announce(searchQuery + ' için ilgili öneri bulunamadı.');
} else {
announce(
searchQuery +
' için ' +
initialCount +
' öneri gösteriliyor' +
(uniqueResults.length > 12 ? ', toplam ' + uniqueResults.length + ' video bulundu' : '') +
'.'
);
}
})
.catch(function (err) {
console.error('[YakTube] Related fetch error:', err);
container.style.display = 'none';
})
.finally(function () {
isFetchingRelated = false;
});
}
var lastWatchUuid = null;
function checkAndInjectWatchPageComments() {
var pathname = window.location.pathname;
var match = pathname.match(/\/videos\/watch\/([a-zA-Z0-9_-]+)/) || pathname.match(/\/w\/([a-zA-Z0-9_-]+)/);
if (!match) {
lastWatchUuid = null;
var existingWatchComments = document.getElementById('yaktube-watch-comments-panel');
if (existingWatchComments) existingWatchComments.remove();
return;
}
var uuid = match[1];
var existingPanel = document.getElementById('yaktube-watch-comments-panel');
if (uuid === lastWatchUuid && existingPanel) {
var nativeComments = document.querySelector('my-video-comments, .video-comments, .comments-block, #comments');
if (nativeComments && existingPanel.previousElementSibling !== nativeComments) {
nativeComments.insertAdjacentElement('afterend', existingPanel);
}
return;
}
lastWatchUuid = uuid;
var mountTarget =
document.querySelector('my-video-comments, .video-comments, my-video-watch, .video-bottom') || document.body;
if (!mountTarget) return;
fetch('/api-custom/video-origin/' + encodeURIComponent(uuid))
.then(function (r) {
return r.json();
})
.then(function (originData) {
if (!originData || !originData.ok || !originData.hasYouTubeOrigin || !originData.youtubeId) {
var old = document.getElementById('yaktube-watch-comments-panel');
if (old) old.remove();
return;
}
var youtubeId = originData.youtubeId;
var existing = document.getElementById('yaktube-watch-comments-panel');
if (existing) existing.remove();
var panel = document.createElement('div');
panel.id = 'yaktube-watch-comments-panel';
panel.className = 'yaktube-comments-panel';
panel.setAttribute('role', 'region');
panel.setAttribute('aria-label', 'YouTube Orijinal Yorumlar\u0131');
panel.style.cssText =
'margin-top: 24px; margin-bottom: 24px; background: #0f172a; border-radius: 12px; padding: 20px; border: 1px solid rgba(255,255,255,0.08); box-shadow: 0 8px 24px rgba(0,0,0,0.4);';
panel.innerHTML =
'
' +
'
' +
'
' +
"\ud83d\udcac YouTube'daki Orijinal Yorumlar" +
'
' +
'
Bu video YouTube\'dan aktar\u0131lm\u0131\u015ft\u0131r. Orijinal topluluk yorumlar\u0131n\u0131 a\u015fa\u011f\u0131dan anl\u0131k olarak y\u00fckleyebilirsiniz.
' +
'
' +
'' +
'
' +
'' +
'
' +
'' +
'
';
var nativeComments = document.querySelector('my-video-comments, .video-comments, .comments-block, #comments');
if (nativeComments && nativeComments.parentElement) {
nativeComments.insertAdjacentElement('afterend', panel);
} else {
var watchCol = document.querySelector('.video-info, .video-bottom, my-video-watch, .main-col');
if (watchCol) {
watchCol.appendChild(panel);
} else {
mountTarget.appendChild(panel);
}
}
var watchCommentToken = null;
var listContainer = document.getElementById('yaktube-watch-comments-list');
var toggleBtn = document.getElementById('yaktube-watch-toggle-comments-btn');
var moreWrap = document.getElementById('yaktube-watch-more-comments-wrap');
var moreBtn = document.getElementById('yaktube-watch-more-comments-btn');
function fetchWatchComments(token) {
if (!token) {
toggleBtn.disabled = true;
toggleBtn.textContent = '⏳ Yorumlar Y\u00fckleniyor...';
} else {
moreBtn.disabled = true;
moreBtn.textContent = '⏳ Y\u00fckleniyor...';
}
var fUrl =
'/api-custom/youtube-comments?id=' +
encodeURIComponent(youtubeId) +
(token ? '&token=' + encodeURIComponent(token) : '');
fetch(fUrl)
.then(function (r) {
return r.json();
})
.then(function (res) {
if (!token) {
listContainer.innerHTML = '';
listContainer.style.display = 'flex';
toggleBtn.textContent = '🔄 Yorumlar\u0131 Yenile';
toggleBtn.disabled = false;
} else {
moreBtn.textContent = '➕ Daha Fazla Yorum G\u00f6ster (+20 Yorum)';
moreBtn.disabled = false;
}
var cList = res.comments || [];
if (cList.length === 0 && !token) {
listContainer.innerHTML =
'