From c0af4e86b28bb1b1d7c56544336b8f630fc884ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enes=20Yak=C4=B1=C5=9Ft=C4=B1r?= Date: Thu, 3 Sep 2026 20:16:33 +0300 Subject: [PATCH] feat(search): implement YakNet cloud search history sync with auth.yakhub.com.tr (v1.4.22) --- client.js | 141 ++++++++++++++++++++++++++++++++++++++++++++++++--- package.json | 2 +- 2 files changed, 134 insertions(+), 9 deletions(-) diff --git a/client.js b/client.js index 835faed..8f627dc 100644 --- a/client.js +++ b/client.js @@ -1926,7 +1926,27 @@ try { var activeVoiceRec = null; var isVoiceListening = false; - // Dynamic Search History & Trending Helpers + // Dynamic Search History & Trending Helpers with YakNet Cloud Sync + function isUserLoggedIn() { + try { + var token = localStorage.getItem('access_token'); + var username = localStorage.getItem('username'); + return Boolean(token || username); + } catch (e) { + return false; + } + } + + function isAccountSyncEnabled() { + try { + var userPref = localStorage.getItem('yaktube_sync_search_history'); + if (userPref === 'false') return false; + return isUserLoggedIn(); + } catch (e) { + return false; + } + } + function getRecentSearches() { try { var data = localStorage.getItem('yaktube_recent_searches'); @@ -1943,6 +1963,33 @@ try { return defaults; } + var isSyncingHistory = false; + function syncCloudSearchHistory(callback) { + if (!isAccountSyncEnabled() || isSyncingHistory) return; + isSyncingHistory = true; + + var token = localStorage.getItem('access_token'); + var headers = {}; + if (token) headers['Authorization'] = 'Bearer ' + token; + + fetch('/api-custom/search-history', { + method: 'GET', + headers: headers, + credentials: 'include' + }) + .then(function (res) { return res.json(); }) + .then(function (data) { + isSyncingHistory = false; + if (data && data.status === 'success' && Array.isArray(data.history) && data.history.length > 0) { + localStorage.setItem('yaktube_recent_searches', JSON.stringify(data.history)); + if (typeof callback === 'function') callback(); + } + }) + .catch(function () { + isSyncingHistory = false; + }); + } + function saveRecentSearch(query) { if (!query || query.trim().length < 2) return; var q = query.trim(); @@ -1952,15 +1999,42 @@ try { return item.toLowerCase() !== q.toLowerCase(); }); list.unshift(q); - if (list.length > 8) list = list.slice(0, 8); + if (list.length > 12) list = list.slice(0, 12); localStorage.setItem('yaktube_recent_searches', JSON.stringify(list)); } catch (e) {} + + // If user is logged in and sync is active, sync with YakNet account + if (isAccountSyncEnabled()) { + var token = localStorage.getItem('access_token'); + var headers = { 'Content-Type': 'application/json' }; + if (token) headers['Authorization'] = 'Bearer ' + token; + + fetch('/api-custom/search-history', { + method: 'POST', + headers: headers, + credentials: 'include', + body: JSON.stringify({ query: q }) + }).catch(function () {}); + } } function clearRecentSearches() { try { localStorage.removeItem('yaktube_recent_searches'); } catch (e) {} + + if (isAccountSyncEnabled()) { + var token = localStorage.getItem('access_token'); + var headers = { 'Content-Type': 'application/json' }; + if (token) headers['Authorization'] = 'Bearer ' + token; + + fetch('/api-custom/search-history', { + method: 'DELETE', + headers: headers, + credentials: 'include' + }).catch(function () {}); + } + renderDynamicSearchChips(); announce('Arama geçmişi temizlendi.'); } @@ -1998,17 +2072,49 @@ try { if (!container) return; var recent = getRecentSearches(); + var loggedIn = isUserLoggedIn(); + var syncEnabled = isAccountSyncEnabled(); var html = ''; - // 1. Recent searches section (if any) + // 1. Recent searches section + html += + '
' + + '
🕒 Son Aramalarınız
' + + '
'; + + if (loggedIn) { + var syncTitle = syncEnabled + ? 'YakNet Bulut Eşitlemesi Aktif (Tüm cihazlarınızda senkronize edilir. Kapatmak için tıklayın.)' + : 'Eşitleme Kapalı (Aramalar sadece bu cihazda saklanır. Açmak için tıklayın.)'; + var syncText = syncEnabled ? '☁️ Eşitleme: Açık' : '☁️ Eşitleme: Kapalı'; + var syncBg = syncEnabled ? '#0f766e' : '#334155'; + var syncColor = syncEnabled ? '#5eead4' : '#94a3b8'; + html += + ''; + } else { + html += + '🔒 Bu Cihazda'; + } + if (recent.length > 0) { html += - '
' + - '
🕒 Son Aramalarınız
' + - '' + - '
' + - '
'; + ''; + } + html += '
'; + + if (recent.length > 0) { + html += '
'; recent.forEach(function (term) { var safeTerm = term.replace(/"/g, '"'); html += @@ -2063,6 +2169,24 @@ try { clearRecentSearches(); }); } + + var syncToggleBtn = container.querySelector('#yaktube-sync-toggle-btn'); + if (syncToggleBtn) { + syncToggleBtn.addEventListener('click', function (e) { + e.preventDefault(); + e.stopPropagation(); + var current = localStorage.getItem('yaktube_sync_search_history') !== 'false'; + var next = !current; + localStorage.setItem('yaktube_sync_search_history', next ? 'true' : 'false'); + if (next) { + announce('YakNet arama geçmişi eşitlemesi açıldı.'); + syncCloudSearchHistory(renderDynamicSearchChips); + } else { + announce('Arama geçmişi eşitlemesi kapatıldı. Aramalar sadece bu cihazda saklanacak.'); + } + renderDynamicSearchChips(); + }); + } } function createFullSearchModal() { @@ -2191,6 +2315,7 @@ try { modal.classList.add('yaktube-modal-open'); modal.style.display = 'flex'; renderDynamicSearchChips(); + syncCloudSearchHistory(renderDynamicSearchChips); var inp = modal.querySelector('#yaktube-modal-input'); var clearBtn = modal.querySelector('#yaktube-modal-clear-btn'); diff --git a/package.json b/package.json index f376c64..dfd4d5b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "peertube-plugin-yaktube-ondemand", - "version": "1.4.21", + "version": "1.4.22", "description": "Accessible On-Demand YouTube Import, Live Streams, Smart Recommendations and A11y Engine for PeerTube", "main": "main.js", "library": "./main.js",