From cdd11385397bec2e7bfe0f01e55e0cbe4c3bb466 Mon Sep 17 00:00:00 2001 From: NCCoder2 Date: Mon, 23 Mar 2026 01:54:51 +0000 Subject: [PATCH 1/8] add new games --- public/books/script.js | 60 ++++------ public/pages/embed/index.html | 208 +++++++++++++++++++++++++--------- 2 files changed, 175 insertions(+), 93 deletions(-) diff --git a/public/books/script.js b/public/books/script.js index c1c85eb..a4bcb8b 100644 --- a/public/books/script.js +++ b/public/books/script.js @@ -1,18 +1,15 @@ import { SettingsManager } from "../assets/js/settings_manager.js"; -const BATCH = 60; -const BASE_PATH = '/books/files/k12learning/'; +const BASE_PATH = 'https://goshadow.net/books/files/k12learning/'; const FAV_KEY = 'arcade_favorites'; const settings = new SettingsManager(); let allGames = []; let visible = []; -let rendered = 0; let activeFilter = 'all'; let searchQuery = ''; let favorites = new Set(); -let imgObserver, scrollObserver; async function loadFavorites() { const stored = await settings.get(FAV_KEY); @@ -29,7 +26,8 @@ function isHot(game) { function openGameTab(game) { const gameUrl = BASE_PATH + game.url; - const embedUrl = `embed.html?url=${encodeURIComponent(gameUrl)}`; + const iconUrl = game.imageUrl ? BASE_PATH + game.imageUrl : ''; + const embedUrl = `embed.html?url=${encodeURIComponent(gameUrl)}&title=${encodeURIComponent(game.label || '')}&icon=${encodeURIComponent(iconUrl)}&src=books`; try { const tabsApi = window.parent?.tabs; @@ -43,26 +41,6 @@ function openGameTab(game) { const HEART_FILLED = ``; const HEART_EMPTY = ``; -function setupImgObserver() { - imgObserver = new IntersectionObserver(entries => { - entries.forEach(e => { - if (!e.isIntersecting) return; - const img = e.target; - img.src = img.dataset.src; - img.onload = () => { img.classList.add('loaded'); img.previousElementSibling?.classList.add('hidden'); }; - img.onerror = () => img.remove(); - imgObserver.unobserve(img); - }); - }, { rootMargin: '300px' }); -} - -function setupScrollObserver() { - scrollObserver = new IntersectionObserver(entries => { - if (entries[0].isIntersecting && rendered < visible.length) renderBatch(); - }, { rootMargin: '400px' }); - scrollObserver.observe(document.getElementById('sentinel')); -} - function buildCard(game) { const a = document.createElement('a'); a.className = 'card'; @@ -79,11 +57,20 @@ function buildCard(game) { if (game.imageUrl) { const img = document.createElement('img'); - img.dataset.src = BASE_PATH + game.imageUrl; + img.src = BASE_PATH + game.imageUrl; img.alt = game.label; + img.loading = 'lazy'; img.decoding = 'async'; + img.onload = () => { + if (!img.isConnected) return; + img.classList.add('loaded'); + img.previousElementSibling?.classList.add('hidden'); + }; + img.onerror = () => { + if (!img.isConnected) return; + img.remove(); + }; a.appendChild(img); - imgObserver.observe(img); } if (isHot(game)) { @@ -133,23 +120,21 @@ function buildCard(game) { return a; } -function renderBatch() { +function renderVisible() { const grid = document.getElementById('grid'); - const end = Math.min(rendered + BATCH, visible.length); const frag = document.createDocumentFragment(); - for (let i = rendered; i < end; i++) frag.appendChild(buildCard(visible[i])); + for (let i = 0; i < visible.length; i++) frag.appendChild(buildCard(visible[i])); grid.appendChild(frag); - rendered = end; } function applyFilters() { const q = searchQuery.toLowerCase(); let filtered = allGames.filter(g => { - if (activeFilter === 'favorites') return favorites.has(g.label); + const searchOk = !q || g.label.toLowerCase().includes(q); + if (activeFilter === 'favorites') return favorites.has(g.label) && searchOk; const catOk = activeFilter === 'all' || (g.categories || []).some(c => c.toLowerCase() === activeFilter); - const searchOk = !q || g.label.toLowerCase().includes(q); return catOk && searchOk; }); @@ -161,8 +146,11 @@ function applyFilters() { visible = filtered; } - rendered = 0; const grid = document.getElementById('grid'); + grid.querySelectorAll('img').forEach(img => { + img.onload = null; + img.onerror = null; + }); grid.innerHTML = ''; document.getElementById('countDisplay').textContent = @@ -173,7 +161,7 @@ function applyFilters() { return; } - renderBatch(); + renderVisible(); } function buildFilters(games) { @@ -208,8 +196,6 @@ function debounce(fn, ms) { } async function init() { - setupImgObserver(); - setupScrollObserver(); await loadFavorites(); try { const data = await fetch('learningcourses.json').then(r => r.json()); diff --git a/public/pages/embed/index.html b/public/pages/embed/index.html index 2376f3e..9f6bccc 100644 --- a/public/pages/embed/index.html +++ b/public/pages/embed/index.html @@ -16,67 +16,163 @@ From 4f15e22151d0e77e397d4b49361c9971eb256149 Mon Sep 17 00:00:00 2001 From: NCCoder2 Date: Mon, 23 Mar 2026 02:26:32 +0000 Subject: [PATCH 2/8] Fixed hardcoded goshadow.net into games --- public/books/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/books/script.js b/public/books/script.js index a4bcb8b..1077931 100644 --- a/public/books/script.js +++ b/public/books/script.js @@ -1,6 +1,6 @@ import { SettingsManager } from "../assets/js/settings_manager.js"; -const BASE_PATH = 'https://goshadow.net/books/files/k12learning/'; +const BASE_PATH = 'books/files/k12learning/'; const FAV_KEY = 'arcade_favorites'; const settings = new SettingsManager(); From deee97b619187f367220b0cbdd4d461e4cc8e506 Mon Sep 17 00:00:00 2001 From: NCCoder2 Date: Mon, 23 Mar 2026 02:27:10 +0000 Subject: [PATCH 3/8] frgt a / --- public/books/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/books/script.js b/public/books/script.js index 1077931..ffd16e6 100644 --- a/public/books/script.js +++ b/public/books/script.js @@ -1,6 +1,6 @@ import { SettingsManager } from "../assets/js/settings_manager.js"; -const BASE_PATH = 'books/files/k12learning/'; +const BASE_PATH = '/books/files/k12learning/'; const FAV_KEY = 'arcade_favorites'; const settings = new SettingsManager(); From f0ae3bf8e2b7bd87f1293455dbb26cfb67cbd296 Mon Sep 17 00:00:00 2001 From: NCCoder2 Date: Mon, 23 Mar 2026 02:41:04 +0000 Subject: [PATCH 4/8] sa --- public/books/script.js | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/public/books/script.js b/public/books/script.js index ffd16e6..f800673 100644 --- a/public/books/script.js +++ b/public/books/script.js @@ -45,6 +45,7 @@ function buildCard(game) { const a = document.createElement('a'); a.className = 'card'; a.href = '#'; + a.dataset.gameLabel = game.label; a.addEventListener('click', e => { e.preventDefault(); openGameTab(game); @@ -127,6 +128,29 @@ function renderVisible() { grid.appendChild(frag); } +function updateDisplay() { + const grid = document.getElementById('grid'); + const visibleLabels = new Set(visible.map(g => g.label)); + + grid.querySelectorAll('.card').forEach(card => { + const label = card.dataset.gameLabel; + card.style.display = visibleLabels.has(label) ? '' : 'none'; + }); + + let emptyMsg = grid.querySelector('.empty'); + if (visible.length === 0) { + if (!emptyMsg) { + emptyMsg = document.createElement('div'); + emptyMsg.className = 'empty'; + emptyMsg.innerHTML = 'NO RESULTSTry a different search or filter'; + grid.appendChild(emptyMsg); + } + emptyMsg.style.display = ''; + } else if (emptyMsg) { + emptyMsg.style.display = 'none'; + } +} + function applyFilters() { const q = searchQuery.toLowerCase(); @@ -146,22 +170,10 @@ function applyFilters() { visible = filtered; } - const grid = document.getElementById('grid'); - grid.querySelectorAll('img').forEach(img => { - img.onload = null; - img.onerror = null; - }); - grid.innerHTML = ''; - document.getElementById('countDisplay').textContent = `${visible.length} game${visible.length !== 1 ? 's' : ''}`; - if (visible.length === 0) { - grid.innerHTML = '
NO RESULTSTry a different search or filter
'; - return; - } - - renderVisible(); + updateDisplay(); } function buildFilters(games) { @@ -203,6 +215,8 @@ async function init() { document.getElementById('loading').style.display = 'none'; document.getElementById('grid').style.display = 'grid'; buildFilters(allGames); + visible = allGames; + renderVisible(); applyFilters(); document.getElementById('searchInput').addEventListener('input', debounce(e => { searchQuery = e.target.value; applyFilters(); }, 150)); From 788e295e788b39e64f39ab9464c81cea7606da63 Mon Sep 17 00:00:00 2001 From: NCCoder2 Date: Mon, 23 Mar 2026 02:42:30 +0000 Subject: [PATCH 5/8] r --- public/books/script.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/public/books/script.js b/public/books/script.js index f800673..5948f1c 100644 --- a/public/books/script.js +++ b/public/books/script.js @@ -7,6 +7,7 @@ const settings = new SettingsManager(); let allGames = []; let visible = []; +let previousVisible = new Set(); let activeFilter = 'all'; let searchQuery = ''; let favorites = new Set(); @@ -134,8 +135,16 @@ function updateDisplay() { grid.querySelectorAll('.card').forEach(card => { const label = card.dataset.gameLabel; - card.style.display = visibleLabels.has(label) ? '' : 'none'; + const shouldBeVisible = visibleLabels.has(label); + const wasVisible = previousVisible.has(label); + + // Only update if visibility changed + if (shouldBeVisible !== wasVisible) { + card.style.display = shouldBeVisible ? '' : 'none'; + } }); + + previousVisible = visibleLabels; let emptyMsg = grid.querySelector('.empty'); if (visible.length === 0) { @@ -216,6 +225,7 @@ async function init() { document.getElementById('grid').style.display = 'grid'; buildFilters(allGames); visible = allGames; + previousVisible = new Set(allGames.map(g => g.label)); renderVisible(); applyFilters(); document.getElementById('searchInput').addEventListener('input', From fbcaba915e48117f5016c58ff961b8e66469b975 Mon Sep 17 00:00:00 2001 From: NCCoder2 Date: Mon, 23 Mar 2026 16:20:11 +0000 Subject: [PATCH 6/8] Fixed Ai Model Bug, added claude. --- public/ai.html | 3 ++- public/books/script.js | 15 +++++++++++++++ public/css/ai.css | 9 +++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/public/ai.html b/public/ai.html index ad9849c..7c20def 100644 --- a/public/ai.html +++ b/public/ai.html @@ -43,7 +43,8 @@

ShadowAssistant

- + + diff --git a/public/books/script.js b/public/books/script.js index 5948f1c..6ee10d9 100644 --- a/public/books/script.js +++ b/public/books/script.js @@ -132,6 +132,21 @@ function renderVisible() { function updateDisplay() { const grid = document.getElementById('grid'); const visibleLabels = new Set(visible.map(g => g.label)); + const cardsByLabel = new Map(); + + grid.querySelectorAll('.card').forEach(card => { + cardsByLabel.set(card.dataset.gameLabel, card); + }); + + const orderedCards = []; + for (let i = 0; i < visible.length; i++) { + const card = cardsByLabel.get(visible[i].label); + if (card) orderedCards.push(card); + } + + for (let i = 0; i < orderedCards.length; i++) { + grid.appendChild(orderedCards[i]); + } grid.querySelectorAll('.card').forEach(card => { const label = card.dataset.gameLabel; diff --git a/public/css/ai.css b/public/css/ai.css index d557e98..8cea65d 100644 --- a/public/css/ai.css +++ b/public/css/ai.css @@ -175,6 +175,15 @@ body { padding-right: 36px; } +#model-selector option { + background: var(--primary); + color: var(--accent-light); + outline:none; + border:none; + padding: 10px 12px; +} + + #model-selector:focus { outline: 2px solid var(--accent); } From 211c3bfe3b21a6ac8cb8a61210f8cf06a384a10a Mon Sep 17 00:00:00 2001 From: NCCoder2 Date: Mon, 23 Mar 2026 16:20:23 +0000 Subject: [PATCH 7/8] Removed duped retro bowl --- public/books/learningcourses.json | 8 -------- 1 file changed, 8 deletions(-) diff --git a/public/books/learningcourses.json b/public/books/learningcourses.json index 38aaf97..a63ac91 100644 --- a/public/books/learningcourses.json +++ b/public/books/learningcourses.json @@ -9,14 +9,6 @@ "Shooting" ] }, - { - "label": "Retro Bowl", - "imageUrl": "images/main4/3_33.png", - "url": "gn/33.html", - "categories": [ - "Sports" - ] - }, { "label": "Sky Riders", "url": "arsenic/sky-riders/index.html", From fed9f089b7293d5ab0e8b85cb999d9a16051fa52 Mon Sep 17 00:00:00 2001 From: NCCoder2 Date: Mon, 23 Mar 2026 16:45:45 +0000 Subject: [PATCH 8/8] Pinned hot games to the top --- public/books/script.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/books/script.js b/public/books/script.js index 6ee10d9..70f86bb 100644 --- a/public/books/script.js +++ b/public/books/script.js @@ -178,7 +178,7 @@ function updateDisplay() { function applyFilters() { const q = searchQuery.toLowerCase(); - let filtered = allGames.filter(g => { + const filtered = allGames.filter(g => { const searchOk = !q || g.label.toLowerCase().includes(q); if (activeFilter === 'favorites') return favorites.has(g.label) && searchOk; const catOk = activeFilter === 'all' || @@ -186,7 +186,7 @@ function applyFilters() { return catOk && searchOk; }); - if (activeFilter !== 'favorites' && !q) { + if (activeFilter !== 'favorites') { const hot = filtered.filter(g => isHot(g)); const rest = filtered.filter(g => !isHot(g)); visible = [...hot, ...rest];