+
Waves.
+
+
+ Ctrl + S
-
-
-
+
+
Eruda is loading...
+
+
+
+
+
Ping: Connecting...
+
+
+
Loading latest commit
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/public/assets/css/$.css b/public/assets/css/$.css
index cf4ad1e0..85340279 100644
--- a/public/assets/css/$.css
+++ b/public/assets/css/$.css
@@ -63,7 +63,7 @@ body {
.home-navbar {
transform: translateX(-50%);
- width: 670px;
+ width: 690px;
top: 1%;
margin-bottom: -10px;
margin-left: 50%;
@@ -86,7 +86,7 @@ body {
}
.home-navbar .favicon {
- width: 24px;
+ width: 28px;
height: 24px;
margin-right: -10px;
vertical-align: middle;
@@ -105,7 +105,7 @@ body {
.home-navbar a:hover {
color: #bbbbbb;
- font-size: 16px;
+ font-size: 18px;
}
.home-navbar a:active {
@@ -223,6 +223,26 @@ body {
color: #818181;
}
+.shortcut-indicator {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(calc(-50% + 235px), -50%);
+ font-size: 12px;
+ font-weight: 500;
+ color: #000000;
+ background-color: #c4c4c4;
+ padding: 2px 6px;
+ border-radius: 7px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ animation: fadeIn 0.3s ease;
+}
+
+.shortcut-indicator:hover {
+ background-color: #ffffff;
+}
+
.shortcut-indicator-2 {
position: absolute;
top: 50%;
@@ -236,12 +256,20 @@ body {
border-radius: 7px;
cursor: pointer;
transition: all 0.3s ease;
+ animation: fadeUp 0.3s ease;
}
.shortcut-indicator-2:hover {
background-color: #ffffff;
}
+.arrow-mode {
+ display: inline-block;
+ margin-left: 17px;
+ transition: all 0.3s ease;
+ animation: fadeIn 0.3s ease;
+}
+
#lockIcon {
position: absolute;
left: 25px;
@@ -320,25 +348,6 @@ body {
color: #ffffff69;
}
-.shortcut-indicator {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(calc(-50% + 235px), -50%);
- font-size: 12px;
- font-weight: 500;
- color: #000000;
- background-color: #c4c4c4;
- padding: 2px 6px;
- border-radius: 7px;
- cursor: pointer;
- transition: all 0.3s ease;
-}
-
-.shortcut-indicator:hover {
- background-color: #ffffff;
-}
-
#erudaLoadingScreen {
position: fixed;
top: 50%;
@@ -451,7 +460,7 @@ body {
display: none;
opacity: 0;
transition: opacity 0.3s ease-in-out;
- animation: fadeInOverlay 0.3s ease-in-out forwards;
+ animation: fadeIn 0.3s ease-in-out forwards;
}
#namePrompt {
@@ -578,7 +587,7 @@ body {
}
#namePrompt.fade-out {
- animation: fadeOutPrompt 0.3s ease-in-out forwards;
+ animation: fadeOut 0.3s ease-in-out forwards;
}
#lastest-commit {
@@ -650,6 +659,14 @@ body {
font-size: 14px;
}
+.fadeIn {
+ animation: fadeIn 0.3s ease-in-out forwards;
+}
+
+.fadeOut {
+ animation: fadeOut 0.3s ease-in-out forwards;
+}
+
@keyframes fadeSlideIn {
to {
opacity: 1;
@@ -657,26 +674,6 @@ body {
}
}
-@keyframes fadeIn {
- from {
- opacity: 0;
- }
-
- to {
- opacity: 1;
- }
-}
-
-@keyframes fadeInOverlay {
- 0% {
- opacity: 0;
- }
-
- 100% {
- opacity: 1;
- }
-}
-
@keyframes fadeInPrompt {
0% {
opacity: 0;
@@ -689,7 +686,17 @@ body {
}
}
-@keyframes fadeOutPrompt {
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+
+ to {
+ opacity: 1;
+ }
+}
+
+@keyframes fadeOut {
0% {
opacity: 1;
}
@@ -709,47 +716,6 @@ body {
}
}
-@keyframes swing {
-
- 0%,
- 100% {
- transform: rotate(3deg);
- }
-
- 50% {
- transform: rotate(-3deg);
- }
-}
-
-@keyframes steamLarge {
- 0% {
- stroke-dashoffset: 13;
- opacity: 0.6;
- }
-
- 100% {
- stroke-dashoffset: 39;
- opacity: 0;
- }
-}
-
-@keyframes steamSmall {
- 10% {
- stroke-dashoffset: 9;
- opacity: 0.6;
- }
-
- 80% {
- stroke-dashoffset: 27;
- opacity: 0;
- }
-
- 100% {
- stroke-dashoffset: 27;
- opacity: 0;
- }
-}
-
@keyframes spin {
0% {
transform: rotate(0deg);
diff --git a/public/assets/css/a.css b/public/assets/css/s.css
similarity index 83%
rename from public/assets/css/a.css
rename to public/assets/css/s.css
index b1653f14..2df8a4c9 100644
--- a/public/assets/css/a.css
+++ b/public/assets/css/s.css
@@ -1,16 +1,16 @@
-.apps-page {
+.shortcuts-page {
padding: 100px 20px 40px;
text-align: center;
position: relative;
}
-.apps-page h1 {
+.shortcuts-page h1 {
font-size: 2.5rem;
margin-bottom: 20px;
color: #fff;
}
-.apps-grid {
+.shortcuts-grid {
display: flex;
flex-wrap: wrap;
justify-content: center;
@@ -21,14 +21,14 @@
margin: 0 auto;
}
-.content.apps-page {
+.content.shortcuts-page {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
-.app-card {
+.shortcut-card {
background-color: #08080894;
border-radius: 25px;
padding: 15px 20px;
@@ -48,7 +48,7 @@
animation: fadeIn 2s ease;
}
-.app-card img {
+.shortcut-card img {
width: 100%;
height: 200px;
object-fit: cover;
@@ -57,26 +57,26 @@
transition: all 0.3s ease;
}
-.app-card:hover img {
+.shortcut-card:hover img {
filter: brightness(1);
}
-.app-card:hover {
+.shortcut-card:hover {
background-color: #333333;
}
-.app-card h2 {
+.shortcut-card h2 {
font-size: 1rem;
margin: 10px 0;
color: #fff;
}
-.app-card p {
+.shortcut-card p {
font-size: 1rem;
color: #ccc;
}
-.apps-search-bar {
+.shortcuts-search-bar {
text-align: center;
margin-top: 20px;
margin-bottom: 20px;
@@ -84,12 +84,12 @@
position: relative;
}
-#appSearchInput {
+#shortcutSearchInput {
padding: 14px 30px;
border: 1px solid #ffffff1a;
background-image: url('/assets/images/icons/search.png');
background-size: 35px 35px;
- background-position: 10px center;
+ background-position: 5px center;
background-repeat: no-repeat;
padding-left: 45px;
border-radius: 20px;
@@ -102,12 +102,12 @@
transition: all 0.3s ease;
}
-#appSearchInput:focus,
-#appSearchInput:hover {
+#shortcutSearchInput:focus,
+#shortcutSearchInput:hover {
border: 1px solid #ffffff69;
}
-#appSearchInput::placeholder {
+#shortcutSearchInput::placeholder {
color: #a8a8a8;
}
diff --git a/public/assets/data/a.json b/public/assets/data/s.json
similarity index 98%
rename from public/assets/data/a.json
rename to public/assets/data/s.json
index fab13846..f28a2db2 100644
--- a/public/assets/data/a.json
+++ b/public/assets/data/s.json
@@ -1,5 +1,5 @@
{
- "apps": [
+ "shortcuts": [
{
"icon": "/assets/images/a/crazygames.jpg",
"title": "Crazy Games",
@@ -51,4 +51,4 @@
"link": "https://store.steampowered.com"
}
]
-}
+}
\ No newline at end of file
diff --git a/public/assets/js/$.js b/public/assets/js/$.js
index 2b7e0f30..f6703c3a 100644
--- a/public/assets/js/$.js
+++ b/public/assets/js/$.js
@@ -145,8 +145,8 @@ document.addEventListener('DOMContentLoaded', () => {
const subjects = ['math', 'science', 'history', 'art', 'programming', 'philosophy'];
const randomSubject = subjects[Math.floor(Math.random() * subjects.length)];
try {
- history.replaceState({}, '', `/learning?subject=${randomSubject}`);
- } catch(e) {}
+ history.replaceState({}, '', `/learning?subject=${randomSubject}`);
+ } catch (e) {}
}
function setupIframeNavigationListeners() {
@@ -203,26 +203,25 @@ document.addEventListener('DOMContentLoaded', () => {
try {
const newUrl = iframe.contentWindow ? iframe.contentWindow.location.href : iframe.src;
if (newUrl && newUrl !== 'about:blank') {
- if (currentIndex === -1 || normalizeUrl(historyStack[currentIndex]) !== normalizeUrl(newUrl) || historyStack[currentIndex] !== newUrl ) {
- addToHistory(newUrl);
+ if (currentIndex === -1 || normalizeUrl(historyStack[currentIndex]) !== normalizeUrl(newUrl) || historyStack[currentIndex] !== newUrl) {
+ addToHistory(newUrl);
} else if (historyStack[currentIndex] !== newUrl) {
addToHistory(newUrl, true);
}
} else if (newUrl === 'about:blank' && historyStack.length > 0 && historyStack[currentIndex] !== 'about:blank') {
if (currentIndex > 0) {
- const previousUrl = historyStack[currentIndex -1];
+ const previousUrl = historyStack[currentIndex - 1];
currentIndex--;
iframe.src = previousUrl;
- return;
+ return;
}
}
setupIframeNavigationListeners();
generateSubject();
- if (navbarToggle && navbarToggle.checked && navBar) {
+ if (navbarToggle && navbarToggle.checked && navBar) {
navBar.style.display = 'block';
}
- } catch (error) {
- } finally {
+ } catch (error) {} finally {
updateNavButtons();
updateDecodedSearchInput();
}
@@ -241,7 +240,7 @@ document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => button.classList.remove(animationClass), 200);
}
}
-
+
backIcon.addEventListener('click', () => {
toggleButtonAnimation(backIcon, 'button-animate-back');
if (currentIndex > 0) {
@@ -263,14 +262,14 @@ document.addEventListener('DOMContentLoaded', () => {
updateDecodedSearchInput();
}
});
-
+
refreshIcon.addEventListener('click', () => {
if (refreshIcon) refreshIcon.classList.add('spin');
if (iframe.contentWindow) {
showLoadingScreen(false);
const currentIframeUrl = iframe.contentWindow.location.href;
if (normalizeUrl(currentIframeUrl) !== normalizeUrl(historyStack[currentIndex] || '')) {
- addToHistory(currentIframeUrl);
+ addToHistory(currentIframeUrl);
}
iframe.contentWindow.location.reload(true);
}
@@ -294,30 +293,30 @@ document.addEventListener('DOMContentLoaded', () => {
return query;
} catch (e) {}
}
-
+
if (/^(localhost|(\d{1,3}\.){3}\d{1,3})(:\d+)?(\/.*)?$/.test(query) || query.toLowerCase() === "localhost") {
- if (!query.toLowerCase().startsWith("http:") && !query.toLowerCase().startsWith("https:")) {
+ if (!query.toLowerCase().startsWith("http:") && !query.toLowerCase().startsWith("https:")) {
return `http://${query}`;
- }
- return query;
+ }
+ return query;
}
-
+
try {
const urlWithHttps = new URL(`https://${query}`);
if (urlWithHttps.hostname &&
urlWithHttps.hostname.includes('.') &&
!urlWithHttps.hostname.endsWith('.') &&
urlWithHttps.hostname !== '.' &&
- urlWithHttps.hostname.split('.').pop().length >= 2 &&
- !/^\d+$/.test(urlWithHttps.hostname.split('.').pop())
- ) {
+ urlWithHttps.hostname.split('.').pop().length >= 2 &&
+ !/^\d+$/.test(urlWithHttps.hostname.split('.').pop())
+ ) {
return urlWithHttps.toString();
}
} catch (e) {}
return `https://duckduckgo.com/?q=${encodeURIComponent(query)}&ia=web`;
}
-
+
async function getUrl(url) {
if (typeof __uv$config !== 'undefined' && __uv$config.encodeUrl) {
return Promise.resolve(__uv$config.prefix + __uv$config.encodeUrl(url));
@@ -336,7 +335,7 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
}
-
+
async function handleSearch(query) {
if (!query || !query.trim()) {
showToast('Please enter something in the Search Bar.', 'error', 'warning');
@@ -357,17 +356,20 @@ document.addEventListener('DOMContentLoaded', () => {
if (searchURL.startsWith(window.location.origin + '/assets/g/')) {
finalUrlToLoad = searchURL;
} else if (searchURL.startsWith('/assets/g/')) {
- finalUrlToLoad = new URL(searchURL, window.location.origin).href;
- }
- else {
+ finalUrlToLoad = new URL(searchURL, window.location.origin).href;
+ } else {
try {
const tempUrl = new URL(searchURL);
if (tempUrl.origin === window.location.origin && tempUrl.pathname.startsWith('/assets/g/')) {
finalUrlToLoad = tempUrl.href;
- } else { finalUrlToLoad = await getUrl(searchURL); }
- } catch (e) { finalUrlToLoad = await getUrl(searchURL); }
+ } else {
+ finalUrlToLoad = await getUrl(searchURL);
+ }
+ } catch (e) {
+ finalUrlToLoad = await getUrl(searchURL);
+ }
}
-
+
if (searchInput2) searchInput2.value = decodeUrl(finalUrlToLoad);
iframe.src = finalUrlToLoad;
}
@@ -392,27 +394,47 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
- if (movies) movies.addEventListener('click', e => { e.preventDefault(); APP.handleSearch('https://movies.usewaves.site/'); });
- if (ai) ai.addEventListener('click', e => { e.preventDefault(); APP.handleSearch('https://ai.usewaves.site/'); });
-
+ if (movies) movies.addEventListener('click', e => {
+ e.preventDefault();
+ APP.handleSearch('https://movies.usewaves.site/');
+ });
+ if (ai) ai.addEventListener('click', e => {
+ e.preventDefault();
+ APP.handleSearch('https://ai.usewaves.site/');
+ });
+
function showToast(message, type = 'success', iconType = 'check') {
const toast = document.createElement('div');
toast.className = `toast show ${type}`;
- const icons = { 'check': 'fa-regular fa-check-circle', 'times-circle': 'fa-regular fa-times-circle', 'info': 'fa-regular fa-info-circle', 'warning': 'fa-regular fa-exclamation-triangle', 'heart': 'fa-solid fa-heart' };
+ const icons = {
+ 'check': 'fa-regular fa-check-circle',
+ 'times-circle': 'fa-regular fa-times-circle',
+ 'info': 'fa-regular fa-info-circle',
+ 'warning': 'fa-regular fa-exclamation-triangle',
+ 'heart': 'fa-solid fa-heart'
+ };
toast.innerHTML = `
${message}`;
- const progressBar = document.createElement('div'); progressBar.className = 'progress-bar'; toast.appendChild(progressBar);
- const closeBtn = document.createElement('button'); closeBtn.className = 'toast-close';
+ const progressBar = document.createElement('div');
+ progressBar.className = 'progress-bar';
+ toast.appendChild(progressBar);
+ const closeBtn = document.createElement('button');
+ closeBtn.className = 'toast-close';
closeBtn.innerHTML = '
';
- closeBtn.onclick = () => { toast.classList.add('hide'); setTimeout(() => toast.remove(), 500); };
+ closeBtn.onclick = () => {
+ toast.classList.add('hide');
+ setTimeout(() => toast.remove(), 500);
+ };
toast.appendChild(closeBtn);
document.body.appendChild(toast);
- setTimeout(() => { toast.classList.add('hide'); setTimeout(() => toast.remove(), 500); }, 3000);
+ setTimeout(() => {
+ toast.classList.add('hide');
+ setTimeout(() => toast.remove(), 500);
+ }, 3000);
}
-
+
if (navbarToggle && navBar && iframe) {
const savedNavbarState = localStorage.getItem('navbarToggled');
- const defaultChecked = iframe.style.display !== 'block' ? true : (savedNavbarState === null ? false : savedNavbarState === 'true');
- navbarToggle.checked = defaultChecked;
+ navbarToggle.checked = savedNavbarState !== 'false';
const updateNavbarDisplayBasedOnToggle = () => {
if (iframe.style.display === 'block') {
@@ -422,15 +444,15 @@ document.addEventListener('DOMContentLoaded', () => {
}
};
updateNavbarDisplayBasedOnToggle();
-
+
navbarToggle.addEventListener('change', () => {
localStorage.setItem('navbarToggled', navbarToggle.checked.toString());
updateNavbarDisplayBasedOnToggle();
});
-
+
window.APP.updateNavbarDisplay = updateNavbarDisplayBasedOnToggle;
}
-
+
window.addEventListener('load', () => {
let iframeInitiallyHidden = true;
if (iframe.src && iframe.src !== 'about:blank') {
@@ -445,8 +467,8 @@ document.addEventListener('DOMContentLoaded', () => {
if (topBar) topBar.style.display = 'flex';
iframe.style.display = 'block';
}
-
- if(window.APP.updateNavbarDisplay) window.APP.updateNavbarDisplay();
+
+ if (window.APP.updateNavbarDisplay) window.APP.updateNavbarDisplay();
updateNavButtons();
updateDecodedSearchInput();
});
@@ -456,44 +478,17 @@ document.addEventListener('DOMContentLoaded', () => {
});
(async () => {
- const commitElement = document.getElementById('lastest-commit');
-
- try {
- const res = await fetch('/api/latest-commit');
-
- console.log('Fetching latest commit from API:', res);
-
- if (!res.ok) {
- const remaining = res.headers.get('X-RateLimit-Remaining');
- const reset = res.headers.get('X-RateLimit-Reset');
-
- console.warn(`Status: ${res.status}`);
- if (remaining !== null) {
- console.warn(`Rate limit remaining: ${remaining}`);
- if (Number(remaining) === 0) {
- const resetDate = reset ? new Date(Number(reset) * 1000) : 'unknown';
- throw new Error(`Rate limit exceeded. Try again at ${resetDate}`);
- }
- }
-
- if (res.status === 403) {
- throw new Error('403 Forbidden — possibly rate limited or blocked.');
- }
-
- throw new Error(`HTTP error! status: ${res.status}`);
+ try {
+ const res = await fetch('/api/latest-commit');
+ const {
+ updates
+ } = await res.json();
+ const u = updates[0];
+ const commitUrl = `https://github.com/xojw/waves/commit/${u.sha}`;
+ document.getElementById('lastest-commit').innerHTML =
+ `
${u.sha}`;
+ } catch {
+ document.getElementById('lastest-commit').textContent =
+ 'Failed to load lastest commit';
}
-
- const { updates } = await res.json();
- const u = updates[0];
- const commitUrl = `https://github.com/xojw/waves/commit/${u.sha}`;
-
- commitElement.innerHTML = `
-
- ${u.sha}
- `;
- } catch (err) {
- console.error('Failed to fetch latest commit:', err.message || err);
-
- commitElement.textContent = 'Failed to load latest commit';
- }
})();
\ No newline at end of file
diff --git a/public/assets/js/a.js b/public/assets/js/a.js
deleted file mode 100644
index 6989c00d..00000000
--- a/public/assets/js/a.js
+++ /dev/null
@@ -1,45 +0,0 @@
-document.addEventListener('DOMContentLoaded', function() {
- const searchInput = document.getElementById('appSearchInput');
- const grid = document.querySelector('.apps-grid');
- let appsData = [];
-
- fetch('/assets/data/a.json')
- .then(response => response.json())
- .then(data => {
- appsData = data.apps;
-
- searchInput.placeholder = `Search through ${appsData.length} Apps…`;
-
- displayApps(appsData);
-
- searchInput.addEventListener('input', function() {
- const query = searchInput.value.toLowerCase();
- const filteredApps = appsData.filter(app => {
- const title = app.title ? app.title.toLowerCase() : '';
- const description = app.description ? app.description.toLowerCase() : '';
- return title.includes(query) || description.includes(query);
- });
- displayApps(filteredApps);
- });
- })
- .catch(err => console.error('Error loading apps data:', err));
-
- function displayApps(apps) {
- grid.innerHTML = '';
- if (apps.length === 0) {
- grid.innerHTML = '
Zero apps were found matching your search :(
';
- }
- apps.forEach(app => {
- const card = document.createElement('div');
- card.classList.add('app-card');
- card.innerHTML = `
-

-
${app.title}
- `;
- card.addEventListener('click', function() {
- window.handleSearch(app.link);
- });
- grid.appendChild(card);
- });
- }
-});
\ No newline at end of file
diff --git a/public/assets/js/g.js b/public/assets/js/g.js
index 194fa274..9de0c6eb 100644
--- a/public/assets/js/g.js
+++ b/public/assets/js/g.js
@@ -1,98 +1,69 @@
-document.addEventListener('DOMContentLoaded', () => {
+document.addEventListener('DOMContentLoaded', function() {
const searchInput = document.getElementById('gameSearchInput');
- const grid = document.querySelector('.games-grid');
- let gamesData = [];
- let filteredData = [];
- const BATCH_SIZE = 50;
- let renderedCount = 0;
-
+ const grid = document.querySelector('.games-grid');
const sentinel = document.createElement('div');
- sentinel.className = 'sentinel';
- grid.after(sentinel);
+ let allGames = [];
+ let filteredGames = [];
+ let renderedCount = 0;
+ const BATCH_SIZE = 20;
const observer = new IntersectionObserver(entries => {
- entries.forEach(entry => {
- if (entry.isIntersecting) {
- renderNextBatch();
- }
- });
- }, { rootMargin: '200px', threshold: 0.1 });
-
- function debounce(fn, wait = 200) {
- let t;
- return (...args) => {
- clearTimeout(t);
- t = setTimeout(() => fn.apply(this, args), wait);
- };
- }
+ if (entries[0].isIntersecting) loadNextBatch();
+ }, { rootMargin: '500px' });
fetch('/assets/data/g.json')
- .then(r => r.json())
+ .then(res => res.json())
.then(data => {
- gamesData = data;
- filteredData = data;
- searchInput.placeholder = `Search through ${data.length} Games…`;
-
+ allGames = data;
+ filteredGames = data;
+ searchInput.placeholder = `Search through ${allGames.length} Games…`;
+ grid.parentNode.appendChild(sentinel);
observer.observe(sentinel);
- renderNextBatch();
-
- searchInput.addEventListener('input', debounce(() => {
- const q = searchInput.value.trim().toLowerCase();
- filteredData = gamesData.filter(g =>
- (g.name || '').toLowerCase().includes(q)
- );
- resetRendering();
- }, 250));
+ resetAndRender();
})
- .catch(console.error);
+ .catch(err => console.error(err));
- function resetRendering() {
+ searchInput.addEventListener('input', function() {
+ const q = this.value.toLowerCase();
+ filteredGames = allGames.filter(game =>
+ (game.name || '').toLowerCase().includes(q)
+ );
+ resetAndRender();
+ });
+
+ function resetAndRender() {
grid.innerHTML = '';
- renderedCount = 0;
- observer.observe(sentinel);
- renderNextBatch();
- }
-
- function renderNextBatch() {
- const batch = filteredData.slice(renderedCount, renderedCount + BATCH_SIZE);
- if (!batch.length) {
+ renderedCount = 0;
+ if (filteredGames.length === 0) {
+ grid.innerHTML = '
Zero games were found matching your search :(
';
observer.unobserve(sentinel);
return;
}
+ observer.observe(sentinel);
+ loadNextBatch();
+ }
- const frag = document.createDocumentFragment();
- batch.forEach(game => {
+ function loadNextBatch() {
+ const nextCount = Math.min(renderedCount + BATCH_SIZE, filteredGames.length);
+ for (let i = renderedCount; i < nextCount; i++) {
+ const game = filteredGames[i];
const card = document.createElement('div');
- card.className = 'game-card';
+ card.classList.add('game-card');
card.innerHTML = `
-

+
${game.name}
`;
card.addEventListener('click', () => {
- window.handleSearch(`/assets/g/${game.directory}`);
+ const gameUrl = window.location.origin + `/assets/g/${game.directory}`;
+ APP.handleSearch(gameUrl);
});
- frag.appendChild(card);
- });
-
- grid.appendChild(frag);
- renderedCount += batch.length;
-
- preloadNextImages(5);
-
- if (renderedCount >= filteredData.length) {
+ grid.appendChild(card);
+ }
+ renderedCount = nextCount;
+ if (renderedCount >= filteredGames.length) {
observer.unobserve(sentinel);
+ } else {
+ grid.parentNode.appendChild(sentinel);
}
}
-
- function preloadNextImages(limit = 3) {
- const next = filteredData.slice(renderedCount, renderedCount + limit);
- next.forEach(({ directory, image }) => {
- const img = new Image();
- img.src = `/assets/g/${directory}/${image}`;
- });
- }
});
\ No newline at end of file
diff --git a/public/assets/js/greetings.js b/public/assets/js/greetings.js
index c2354c7a..14b344e1 100644
--- a/public/assets/js/greetings.js
+++ b/public/assets/js/greetings.js
@@ -38,8 +38,8 @@ function getWelcomeMessage(name) {
const path = window.location.pathname;
if (path === '/g') {
return `Have fun playing games, ${name}!`;
- } else if (path === '/a') {
- return `Enjoy our collection of apps, ${name}!`;
+ } else if (path === '/s') {
+ return `Enjoy our collection of, ${name}!`;
} else {
return `Welcome back, ${name}!`;
}
@@ -47,7 +47,7 @@ function getWelcomeMessage(name) {
function getIconType(path) {
if (path === '/g') return 'game';
- if (path === '/a') return 'apps';
+ if (path === '/s') return 'shortcuts';
return 'wave';
}
@@ -65,7 +65,7 @@ timeGreetings.push(
{ text: 'Good morning, sunshine', icon: '
', suffix: ' :D' },
{ text: 'Here’s to a bright morning', icon: '
', suffix: '.' },
{ text: 'Enjoy your morning', icon: '
', suffix: '!' },
- { text: 'Your day starts here', icon: '
', suffix: ' !' }
+ { text: 'Your day starts here', icon: '
', suffix: '!' }
);
timeGreetings.push(
diff --git a/public/assets/js/register.js b/public/assets/js/register.js
index b833de2a..158e58d5 100644
--- a/public/assets/js/register.js
+++ b/public/assets/js/register.js
@@ -1,89 +1,80 @@
-document.addEventListener('DOMContentLoaded', function() {
+;(function(){
+ const origLog = console.log.bind(console);
+ document.addEventListener("DOMContentLoaded", () => {
+ origLog(
+ "%c\n" +
+ " ᶻ 𝗓 𐰁 .ᐟ\n" +
+ " |\\ _,,,---,,_\n" +
+ " /, `.-'`' -. ;-;;,_\n" +
+ " |,4- ) )-,_..;\\ ( `'-'\n" +
+ " '---''(_/--' `-`\\_)\n discord.gg/dJvdkPRheV",
+ "color: hotpink; font-size: 16px; display: block; white-space: pre; text-align: center; padding-left: 28%;"
+ );
+ });
- const defaultWispUrl = `${window.location.protocol === "https:" ? "wss" : "ws"}://${window.location.host}/w/`;
- let currentWispUrl = localStorage.getItem('customWispUrl') || defaultWispUrl;
- const wispUrl = currentWispUrl;
- const connection = new BareMux.BareMuxConnection("/baremux/worker.js");
+ const labelStyle = "background: white; color: black; font-weight: bold; padding: 2px 4px; border-radius: 2px";
+ const messageStyle = "background: black; color: white; padding: 2px 4px; border-radius: 2px";
+ ["log","info","warn","error","debug"].forEach(method => {
+ const orig = console[method].bind(console);
+ console[method] = (...args) => {
+ const text = args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ');
+ orig(`%cWaves:%c ${text}`, labelStyle, messageStyle);
+ };
+ });
- async function registerSW() {
- try {
- if (!navigator.serviceWorker) {
- console.log("%c[!]%c Service Workers are not supported by this browser.", "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
- return;
- }
- await ensureWebSocketConnection(wispUrl);
- console.log("%c[+]%c Registering Service Worker...", "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
- await navigator.serviceWorker.register("/wah/sw.js", { scope: '/wah/a/' });
- console.log("%c[*]%c Service Worker registered successfully.", "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
- const savedTransport = localStorage.getItem('transport') || "epoxy";
- switchTransport(savedTransport);
- updateTransportUI(savedTransport);
- console.log(`%c[#]%c Using ${capitalizeTransport(savedTransport)} transport.`, "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
- } catch (error) {
- logError(error, 'An error occurred during Service Worker registration or WebSocket connection');
- }
- }
+ document.addEventListener("DOMContentLoaded", function(){
+ const defaultWispUrl = `${window.location.protocol==="https:"?"wss":"ws"}://${window.location.host}/w/`;
+ let currentWispUrl = localStorage.getItem("customWispUrl") || defaultWispUrl;
+ const wispUrl = currentWispUrl;
+ const connection = new BareMux.BareMuxConnection("/baremux/worker.js");
- async function ensureWebSocketConnection(url) {
- return new Promise((resolve, reject) => {
- console.log("%c[+]%c Establishing WebSocket connection...", "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
- const ws = new WebSocket(url);
- ws.onopen = () => {
- console.log("%c[*]%c WebSocket connection established.", "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
- resolve(ws);
- };
- ws.onerror = (error) => {
- logError(error, 'Failed to establish WebSocket connection');
- reject(error);
- };
- ws.onclose = (event) => {
- if (event.code !== 1000) {
- console.warn(`%c[-]%c WebSocket connection closed. Reason: ${event.reason || "No reason provided"}`, "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
- } else {
- console.warn("%c[-]%c WebSocket connection closed normally.", "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
- }
- };
- });
- }
+ registerSW();
- function logError(error, message) {
- console.error(`%c[!]%c ${message}: ${error.message || error}`, "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
- }
+ async function registerSW(){
+ try {
+ if (!navigator.serviceWorker) return console.error("Service Workers are not supported by this browser.");
+ await ensureWebSocketConnection(wispUrl);
+ console.log("Registering Service Worker...");
+ await navigator.serviceWorker.register("/wah/sw.js", { scope: "/wah/a/" });
+ console.log("Service Worker registered successfully.");
+ const savedTransport = localStorage.getItem("transport") || "epoxy";
+ switchTransport(savedTransport);
+ updateTransportUI(savedTransport);
+ console.log(`Using ${capitalizeTransport(savedTransport)} transport.`);
+ } catch (e) {
+ console.error(`An error occurred during Service Worker registration or WebSocket connection: ${e.message||e}`);
+ }
+ }
- function switchTransport(transport) {
- const transportMap = {
- "epoxy": "/epoxy/index.mjs",
- "libcurl": "/libcurl/index.mjs"
- };
- const transportFile = transportMap[transport];
- if (transportFile) {
- connection.setTransport(transportFile, [{ wisp: wispUrl }]);
- }
- }
+ async function ensureWebSocketConnection(url){
+ return new Promise((resolve, reject) => {
+ console.log("Establishing WebSocket connection...");
+ const ws = new WebSocket(url);
+ ws.onopen = () => { console.log("WebSocket connection established."); resolve(ws); };
+ ws.onerror = e => { console.error(`Failed to establish WebSocket connection: ${e.message||e}`); reject(e); };
+ ws.onclose = ev => {
+ if (ev.code !== 1000) console.warn(`WebSocket connection closed. Reason: ${ev.reason||"No reason provided"}`);
+ else console.warn("WebSocket connection closed normally.");
+ };
+ });
+ }
- async function changeTransport(newTransport) {
- try {
- localStorage.setItem('transport', newTransport);
- switchTransport(newTransport);
- updateTransportUI(newTransport);
- } catch (error) {
- logError(error, 'An error occurred while storing transport preference');
- }
- }
+ function switchTransport(t){
+ const m = { epoxy: "/epoxy/index.mjs", libcurl: "/libcurl/index.mjs" }[t];
+ if (m) connection.setTransport(m, [{ wisp: wispUrl }]);
+ }
- function updateTransportUI(transport) {
- const transportSelected = document.querySelector(".transport-selected");
- transportSelected.textContent = capitalizeTransport(transport);
- }
+ function updateTransportUI(t){
+ document.querySelector(".transport-selected").textContent = capitalizeTransport(t);
+ }
- function capitalizeTransport(transport) {
- return transport.charAt(0).toUpperCase() + transport.slice(1).toLowerCase();
- }
+ function capitalizeTransport(t){
+ return t.charAt(0).toUpperCase() + t.slice(1).toLowerCase();
+ }
- document.addEventListener('wispUrlChanged', function(e) {
- currentWispUrl = e.detail;
- switchTransport(localStorage.getItem('transport') || "epoxy");
- });
-
- registerSW();
-});
\ No newline at end of file
+ document.addEventListener("wispUrlChanged", function(e){
+ currentWispUrl = e.detail;
+ switchTransport(localStorage.getItem("transport") || "epoxy");
+ });
+ });
+})();
\ No newline at end of file
diff --git a/public/assets/js/s.js b/public/assets/js/s.js
new file mode 100644
index 00000000..ab01a157
--- /dev/null
+++ b/public/assets/js/s.js
@@ -0,0 +1,45 @@
+document.addEventListener('DOMContentLoaded', function() {
+ const searchInput = document.getElementById('shortcutSearchInput');
+ const grid = document.querySelector('.shortcuts-grid');
+ let shortcutsData = [];
+
+ fetch('/assets/data/s.json')
+ .then(response => response.json())
+ .then(data => {
+ shortcutsData = data.shortcuts;
+
+ searchInput.placeholder = `Search through ${shortcutsData.length} Shortcuts...`;
+
+ displayShortcuts(shortcutsData);
+
+ searchInput.addEventListener('input', function() {
+ const query = searchInput.value.toLowerCase();
+ const filteredShortcuts = shortcutsData.filter(shortcut => {
+ const title = shortcut.title ? shortcut.title.toLowerCase() : '';
+ const description = shortcut.description ? shortcut.description.toLowerCase() : '';
+ return title.includes(query) || description.includes(query);
+ });
+ displayShortcuts(filteredShortcuts);
+ });
+ })
+ .catch(err => console.error('Error loading shortcuts data:', err));
+
+ function displayShortcuts(shortcuts) {
+ grid.innerHTML = '';
+ if (shortcuts.length === 0) {
+ grid.innerHTML = '
Zero shortcuts were found matching your search :(
';
+ }
+ shortcuts.forEach(shortcut => {
+ const card = document.createElement('div');
+ card.classList.add('shortcut-card');
+ card.innerHTML = `
+

+
${shortcut.title}
+ `;
+ card.addEventListener('click', function() {
+ APP.handleSearch(shortcut.link);
+ });
+ grid.appendChild(card);
+ });
+ }
+});
\ No newline at end of file
diff --git a/public/assets/js/settings.js b/public/assets/js/settings.js
index 7d0154b3..4890d269 100644
--- a/public/assets/js/settings.js
+++ b/public/assets/js/settings.js
@@ -1,6 +1,6 @@
-document.addEventListener('DOMContentLoaded', function () {
- const settingsMenu = document.getElementById('settings-menu');
- settingsMenu.innerHTML = `
+document.addEventListener('DOMContentLoaded', function() {
+ const settingsMenu = document.getElementById('settings-menu');
+ settingsMenu.innerHTML = `
Settings
`;
- const settingsIcon = document.getElementById('settings-icon');
- const closeSettingsBtn = document.getElementById('close-settings');
- const saveWispBtn = document.getElementById('save-wisp-url');
- const transportSelector = document.querySelector('.transport-selector');
- const transportSelected = transportSelector.querySelector('.transport-selected');
- const transportOptions = transportSelector.querySelector('.transport-options');
- const navbarToggle = document.getElementById('navbar-toggle');
- const defaultWispUrl = `${window.location.protocol === "https:" ? "wss" : "ws"}://${window.location.host}/w/`;
- let currentWispUrl = localStorage.getItem('customWispUrl') || defaultWispUrl;
- const wispInput = document.querySelector("#wisp-server");
- wispInput.value = currentWispUrl;
- let isToggling = false;
+ const settingsIcon = document.getElementById('settings-icon');
+ const closeSettingsBtn = document.getElementById('close-settings');
+ const saveWispBtn = document.getElementById('save-wisp-url');
+ const transportSelector = document.querySelector('.transport-selector');
+ const transportSelected = transportSelector.querySelector('.transport-selected');
+ const transportOptions = transportSelector.querySelector('.transport-options');
+ const navbarToggle = document.getElementById('navbar-toggle');
+ const defaultWispUrl = `${window.location.protocol === "https:" ? "wss" : "ws"}://${window.location.host}/w/`;
+ let currentWispUrl = localStorage.getItem('customWispUrl') || defaultWispUrl;
+ const wispInput = document.querySelector("#wisp-server");
+ wispInput.value = currentWispUrl;
+ let isToggling = false;
- function isValidUrl(url) {
- try {
- const p = new URL(url);
- return (p.protocol === "wss:" || p.protocol === "ws:") && url.endsWith('/');
- } catch (_) {
- return false;
+ navbarToggle.checked = localStorage.getItem('navbarToggled') !== 'false';
+
+ function isValidUrl(url) {
+ try {
+ const p = new URL(url);
+ return (p.protocol === "wss:" || p.protocol === "ws:") && url.endsWith('/');
+ } catch (_) {
+ return false;
+ }
}
- }
function runScriptIfChecked() {
- let inFrame;
- try {
- inFrame = window !== top;
- } catch (e) {
- inFrame = true;
- }
- const aboutBlankChecked = JSON.parse(localStorage.getItem("aboutBlankChecked")) || false;
- if (!aboutBlankChecked || inFrame) {
- return;
- }
- const defaultTitle = "Google.";
- const defaultIcon = "https://www.google.com/favicon.ico";
- const title = localStorage.getItem("siteTitle") || defaultTitle;
- const icon = localStorage.getItem("faviconURL") || defaultIcon;
- const iframeSrc = "/";
- const popup = window.open("", "_blank");
- if (!popup || popup.closed) {
- alert("Failed to load automask. Please allow popups and try again.");
- return;
- }
- popup.document.head.innerHTML = `
+ let inFrame;
+ try {
+ inFrame = window !== top;
+ } catch (e) {
+ inFrame = true;
+ }
+ const aboutBlankChecked = JSON.parse(localStorage.getItem("aboutBlankChecked")) || false;
+ if (!aboutBlankChecked || inFrame) {
+ return;
+ }
+ const defaultTitle = "Google.";
+ const defaultIcon = "https://www.google.com/favicon.ico";
+ const title = localStorage.getItem("siteTitle") || defaultTitle;
+ const icon = localStorage.getItem("faviconURL") || defaultIcon;
+ const iframeSrc = "/";
+ const popup = window.open("", "_blank");
+ if (!popup || popup.closed) {
+ alert("Failed to load automask. Please allow popups and try again.");
+ return;
+ }
+ popup.document.head.innerHTML = `
${title}
`;
- popup.document.body.innerHTML = `
+ popup.document.body.innerHTML = `
`;
- window.location.replace("https://bisd.schoology.com/home");
- }
- document.getElementById("aboutblank-toggle").addEventListener("change", function() {
- localStorage.setItem("aboutBlankChecked", JSON.stringify(this.checked));
- if (this.checked) {
- showToast('success', 'Auto About:Blank is now enabled.');
- } else {
- showToast('error', 'Auto About:Blank is now disabled.');
- }
- runScriptIfChecked();
- });
- window.addEventListener("load", function() {
- const aboutBlankChecked = JSON.parse(localStorage.getItem("aboutBlankChecked")) || false;
- document.getElementById("aboutblank-toggle").checked = aboutBlankChecked;
- runScriptIfChecked();
- });
-
- function updateWispServerUrl(url) {
- if (isValidUrl(url)) {
- currentWispUrl = url;
- localStorage.setItem('customWispUrl', url);
- document.dispatchEvent(new CustomEvent('wispUrlChanged', { detail: currentWispUrl }));
- showToast('success', `Wisp Server URL changed to: ${currentWispUrl}`);
- } else {
- currentWispUrl = defaultWispUrl;
- localStorage.setItem('customWispUrl', defaultWispUrl);
- document.dispatchEvent(new CustomEvent('wispUrlChanged', { detail: currentWispUrl }));
- showToast('error', "Invalid URL. Reverting to default...");
+ window.location.replace("https://bisd.schoology.com/home");
}
- }
- function updateServerInfo() {
- const speedSpan = document.getElementById('server-speed');
- const uptimeSpan = document.getElementById('server-uptime');
- const specsSpan = document.getElementById('server-specs');
- let uptimeInterval;
-
- fetch('/api/info')
- .then(response => {
- if (!response.ok) throw new Error();
- return response.json();
- })
- .then(data => {
- if (data?.speed) {
- const updateUptimeDisplay = () => {
- const uptime = Date.now() - data.startTime;
- const days = Math.floor(uptime / 86400000);
- const hours = Math.floor((uptime % 86400000) / 3600000);
- const minutes = Math.floor((uptime % 3600000) / 60000);
- const seconds = Math.floor((uptime % 60000) / 1000);
- uptimeSpan.textContent = `${days}d ${hours}h ${minutes}m ${seconds}s`;
- };
-
- updateUptimeDisplay();
- clearInterval(uptimeInterval);
- uptimeInterval = setInterval(updateUptimeDisplay, 1000);
-
- speedSpan.textContent = `${data.speed} (${data.averageLatency}ms)`;
- specsSpan.textContent = data.specs;
+ document.getElementById("aboutblank-toggle").addEventListener("change", function() {
+ localStorage.setItem("aboutBlankChecked", JSON.stringify(this.checked));
+ if (this.checked) {
+ showToast('success', 'Auto About:Blank is now enabled.');
+ } else {
+ showToast('error', 'Auto About:Blank is now disabled.');
}
- setTimeout(updateServerInfo, 10000);
- })
- .catch(() => {
- speedSpan.textContent = 'Connection error';
- setTimeout(updateServerInfo, 30000);
- });
- }
+ runScriptIfChecked();
+ });
- function initializeInfo() {
- const infoTab = document.getElementById('info-tab');
- const infoContent = document.getElementById('info-content');
+ window.addEventListener("load", function() {
+ const aboutBlankChecked = JSON.parse(localStorage.getItem("aboutBlankChecked")) || false;
+ document.getElementById("aboutblank-toggle").checked = aboutBlankChecked;
+ runScriptIfChecked();
+ });
- const startMonitoring = () => {
- updateServerInfo();
- infoTab.removeEventListener('click', startMonitoring);
- };
-
- if (infoContent.classList.contains('active')) {
- updateServerInfo();
- } else {
- infoTab.addEventListener('click', startMonitoring, { once: true });
+ function updateWispServerUrl(url) {
+ if (isValidUrl(url)) {
+ currentWispUrl = url;
+ localStorage.setItem('customWispUrl', url);
+ document.dispatchEvent(new CustomEvent('wispUrlChanged', {
+ detail: currentWispUrl
+ }));
+ showToast('success', `Wisp Server URL changed to: ${currentWispUrl}`);
+ } else {
+ currentWispUrl = defaultWispUrl;
+ localStorage.setItem('customWispUrl', defaultWispUrl);
+ document.dispatchEvent(new CustomEvent('wispUrlChanged', {
+ detail: currentWispUrl
+ }));
+ showToast('error', "Invalid URL. Reverting to default...");
+ }
}
- }
- function showToast(type, message) {
- const toast = document.createElement('div');
- toast.className = `toast ${type} show`;
- const icons = {
- success: '',
- error: '',
- info: '',
- warning: ''
- };
- toast.innerHTML = `${icons[type]||''}${message}`;
- const progressBar = document.createElement('div');
- progressBar.className = 'progress-bar';
- toast.appendChild(progressBar);
- const closeBtn = document.createElement('button');
- closeBtn.className = 'toast-close';
- closeBtn.innerHTML = '';
- closeBtn.addEventListener('click', () => {
- toast.classList.replace('show', 'hide');
- setTimeout(() => toast.remove(), 500);
- });
- toast.appendChild(closeBtn);
- document.body.appendChild(toast);
- setTimeout(() => {
- toast.classList.replace('show', 'hide');
- setTimeout(() => toast.remove(), 500);
- }, 3000);
- }
- saveWispBtn.addEventListener('click', () => updateWispServerUrl(wispInput.value.trim()));
- settingsIcon.addEventListener('click', e => {
- e.preventDefault();
- toggleSettingsMenu();
- });
- closeSettingsBtn.addEventListener('click', toggleSettingsMenu);
- function toggleSettingsMenu() {
- if (isToggling) return;
- isToggling = true;
- const icon = document.querySelector('#settings-icon i.settings-icon');
- if (settingsMenu.classList.contains('open')) {
- settingsMenu.classList.add('close');
- icon.classList.replace('fa-solid', 'fa-regular');
- setTimeout(() => {
- settingsMenu.classList.remove('open', 'close');
- isToggling = false;
- }, 300);
- } else {
- settingsMenu.classList.add('open');
- icon.classList.replace('fa-regular', 'fa-solid');
- setTimeout(() => {
- settingsMenu.classList.remove('close');
- isToggling = false;
- }, 300);
+ function updateServerInfo() {
+ const speedSpan = document.getElementById('server-speed');
+ const uptimeSpan = document.getElementById('server-uptime');
+ const specsSpan = document.getElementById('server-specs');
+ let uptimeInterval;
+
+ fetch('/api/info')
+ .then(response => {
+ if (!response.ok) throw new Error();
+ return response.json();
+ })
+ .then(data => {
+ if (data?.speed) {
+ const updateUptimeDisplay = () => {
+ const uptime = Date.now() - data.startTime;
+ const days = Math.floor(uptime / 86400000);
+ const hours = Math.floor((uptime % 86400000) / 3600000);
+ const minutes = Math.floor((uptime % 3600000) / 60000);
+ const seconds = Math.floor((uptime % 60000) / 1000);
+ uptimeSpan.textContent = `${days}d ${hours}h ${minutes}m ${seconds}s`;
+ };
+
+ updateUptimeDisplay();
+ clearInterval(uptimeInterval);
+ uptimeInterval = setInterval(updateUptimeDisplay, 1000);
+
+ speedSpan.textContent = `${data.speed} (${data.averageLatency}ms)`;
+ specsSpan.textContent = data.specs;
+ }
+ setTimeout(updateServerInfo, 10000);
+ })
+ .catch(() => {
+ speedSpan.textContent = 'Connection error';
+ setTimeout(updateServerInfo, 30000);
+ });
}
- }
- transportSelected.addEventListener('click', e => {
- e.stopPropagation();
- transportOptions.classList.toggle('transport-show');
- transportSelected.classList.toggle('transport-arrow-active');
- });
+ function initializeInfo() {
+ const infoTab = document.getElementById('info-tab');
+ const infoContent = document.getElementById('info-content');
- Array.from(transportOptions.getElementsByTagName('div')).forEach(option => {
- option.addEventListener('click', function (e) {
- e.stopPropagation();
- const val = this.textContent;
- transportSelected.textContent = val;
- localStorage.setItem('transport', val.toLowerCase());
- transportOptions.classList.remove('transport-show');
- transportSelected.classList.remove('transport-arrow-active');
- document.dispatchEvent(new CustomEvent('newTransport', { detail: val.toLowerCase() }));
- showToast('success', `Transport changed to ${val}`);
+ const startMonitoring = () => {
+ updateServerInfo();
+ infoTab.removeEventListener('click', startMonitoring);
+ };
+
+ if (infoContent.classList.contains('active')) {
+ updateServerInfo();
+ } else {
+ infoTab.addEventListener('click', startMonitoring, {
+ once: true
+ });
+ }
+ }
+
+ function showToast(type, message) {
+ const toast = document.createElement('div');
+ toast.className = `toast ${type} show`;
+ const icons = {
+ success: '',
+ error: '',
+ info: '',
+ warning: ''
+ };
+ toast.innerHTML = `${icons[type]||''}${message}`;
+ const progressBar = document.createElement('div');
+ progressBar.className = 'progress-bar';
+ toast.appendChild(progressBar);
+ const closeBtn = document.createElement('button');
+ closeBtn.className = 'toast-close';
+ closeBtn.innerHTML = '';
+ closeBtn.addEventListener('click', () => {
+ toast.classList.replace('show', 'hide');
+ setTimeout(() => toast.remove(), 500);
+ });
+ toast.appendChild(closeBtn);
+ document.body.appendChild(toast);
+ setTimeout(() => {
+ toast.classList.replace('show', 'hide');
+ setTimeout(() => toast.remove(), 500);
+ }, 3000);
+ }
+
+ saveWispBtn.addEventListener('click', () => updateWispServerUrl(wispInput.value.trim()));
+ settingsIcon.addEventListener('click', e => {
+ e.preventDefault();
+ toggleSettingsMenu();
});
- });
+ closeSettingsBtn.addEventListener('click', toggleSettingsMenu);
- document.getElementById('proxy-content').classList.add('active');
+ function toggleSettingsMenu() {
+ if (isToggling) return;
+ isToggling = true;
+ const icon = document.querySelector('#settings-icon i.settings-icon');
+ if (settingsMenu.classList.contains('open')) {
+ settingsMenu.classList.add('close');
+ icon.classList.replace('fa-solid', 'fa-regular');
+ setTimeout(() => {
+ settingsMenu.classList.remove('open', 'close');
+ isToggling = false;
+ }, 300);
+ } else {
+ settingsMenu.classList.add('open');
+ icon.classList.replace('fa-regular', 'fa-solid');
+ setTimeout(() => {
+ settingsMenu.classList.remove('close');
+ isToggling = false;
+ }, 300);
+ }
+ }
- function switchTab(activeTab, activeContent, ...others) {
- others.forEach(id => document.getElementById(id).classList.remove('active'));
- document.getElementById(activeTab).classList.add('active');
- document.getElementById(activeContent).classList.add('active');
- }
-
- document.getElementById('proxy-tab').addEventListener('click', () => switchTab('proxy-tab', 'proxy-content', 'cloak-tab', 'cloak-content', 'appearance-tab', 'appearance-content', 'info-tab', 'info-content'));
- document.getElementById('cloak-tab').addEventListener('click', () => switchTab('cloak-tab', 'cloak-content', 'proxy-tab', 'proxy-content', 'appearance-tab', 'appearance-content', 'info-tab', 'info-content'));
- document.getElementById('appearance-tab').addEventListener('click', () => switchTab('appearance-tab', 'appearance-content', 'proxy-tab', 'proxy-content', 'cloak-tab', 'cloak-content', 'info-tab', 'info-content'));
- document.getElementById('info-tab').addEventListener('click', () => switchTab('info-tab', 'info-content', 'proxy-tab', 'proxy-content', 'cloak-tab', 'cloak-content', 'appearance-tab', 'appearance-content'));
-
- document.querySelectorAll('.tab-button').forEach(btn => {
- btn.addEventListener('click', function () {
- const icon = this.querySelector('i');
- if (!icon.classList.contains('fa-bounce')) {
- icon.classList.add('fa-bounce');
- setTimeout(() => icon.classList.remove('fa-bounce'), 750);
- }
+ transportSelected.addEventListener('click', e => {
+ e.stopPropagation();
+ transportOptions.classList.toggle('transport-show');
+ transportSelected.classList.toggle('transport-arrow-active');
});
- });
- navbarToggle.addEventListener('change', function () {
- showToast(this.checked ? 'success' : 'error', `Navigation Bar ${this.checked ? 'enabled' : 'disabled'}`);
- });
+ Array.from(transportOptions.getElementsByTagName('div')).forEach(option => {
+ option.addEventListener('click', function(e) {
+ e.stopPropagation();
+ const val = this.textContent;
+ transportSelected.textContent = val;
+ localStorage.setItem('transport', val.toLowerCase());
+ transportOptions.classList.remove('transport-show');
+ transportSelected.classList.remove('transport-arrow-active');
+ document.dispatchEvent(new CustomEvent('newTransport', {
+ detail: val.toLowerCase()
+ }));
+ showToast('success', `Transport changed to ${val}`);
+ });
+ });
- initializeInfo();
+ document.getElementById('proxy-content').classList.add('active');
+
+ function switchTab(activeTab, activeContent, ...others) {
+ others.forEach(id => document.getElementById(id).classList.remove('active'));
+ document.getElementById(activeTab).classList.add('active');
+ document.getElementById(activeContent).classList.add('active');
+ }
+
+ document.getElementById('proxy-tab').addEventListener('click', () => switchTab('proxy-tab', 'proxy-content', 'cloak-tab', 'cloak-content', 'appearance-tab', 'appearance-content', 'info-tab', 'info-content'));
+ document.getElementById('cloak-tab').addEventListener('click', () => switchTab('cloak-tab', 'cloak-content', 'proxy-tab', 'proxy-content', 'appearance-tab', 'appearance-content', 'info-tab', 'info-content'));
+ document.getElementById('appearance-tab').addEventListener('click', () => switchTab('appearance-tab', 'appearance-content', 'proxy-tab', 'proxy-content', 'cloak-tab', 'cloak-content', 'info-tab', 'info-content'));
+ document.getElementById('info-tab').addEventListener('click', () => switchTab('info-tab', 'info-content', 'proxy-tab', 'proxy-content', 'cloak-tab', 'cloak-content', 'appearance-tab', 'appearance-content'));
+
+ document.querySelectorAll('.tab-button').forEach(btn => {
+ btn.addEventListener('click', function() {
+ const icon = this.querySelector('i');
+ if (!icon.classList.contains('fa-bounce')) {
+ icon.classList.add('fa-bounce');
+ setTimeout(() => icon.classList.remove('fa-bounce'), 750);
+ }
+ });
+ });
+
+ navbarToggle.addEventListener('change', function() {
+ localStorage.setItem('navbarToggled', this.checked.toString());
+ showToast(this.checked ? 'success' : 'error', `Navigation Bar ${this.checked ? 'enabled' : 'disabled'}`);
+ if (window.APP && typeof window.APP.updateNavbarDisplay === 'function') {
+ window.APP.updateNavbarDisplay();
+ }
+ });
+
+ initializeInfo();
});
\ No newline at end of file
diff --git a/public/assets/js/shortcuts.js b/public/assets/js/shortcuts.js
index 919201ee..3f695472 100644
--- a/public/assets/js/shortcuts.js
+++ b/public/assets/js/shortcuts.js
@@ -1,109 +1,147 @@
-(function () {
- document.addEventListener('DOMContentLoaded', function () {
- function getSearchInputs() {
- return [
- document.getElementById('searchInput'),
- document.getElementById('searchInputt'),
- document.getElementById('gameSearchInput'),
- document.getElementById('appSearchInput')
- ].filter(Boolean);
+(function(){
+ document.addEventListener('DOMContentLoaded', function(){
+ const indicators = document.querySelectorAll('.shortcut-indicator, .shortcut-indicator-2, .shortcut-indicator-3, .shortcut-indicator-4');
+ const arrowIndicators = document.querySelectorAll('.shortcut-indicator, .shortcut-indicator-2');
+ indicators.forEach(el => {
+ if (!el.dataset.original) el.dataset.original = el.innerHTML;
+ });
+
+ function getSearchInputs(){
+ return [
+ document.getElementById('searchInput'),
+ document.getElementById('searchInputt'),
+ document.getElementById('gameSearchInput'),
+ document.getElementById('shortcutSearchInput')
+ ].filter(Boolean);
+ }
+
+ function isVisible(el){
+ return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
+ }
+
+ function focusFirstVisibleInput(){
+ const inputs = getSearchInputs();
+ for (let inp of inputs) {
+ if (isVisible(inp)) {
+ inp.focus();
+ return inp;
+ }
}
-
- function isVisible(el) {
- return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
+ if (inputs[0]) {
+ inputs[0].focus();
+ return inputs[0];
}
+ return null;
+ }
- function focusFirstVisibleInput() {
- const inputs = getSearchInputs();
- for (const input of inputs) {
- if (isVisible(input)) {
- input.focus();
- return;
- }
- }
- if (inputs.length) {
- inputs[0].focus();
- }
+ let arrowMode = false;
+
+ function updateIndicatorState(){
+ const hasText = getSearchInputs().some(i => i.value.trim() !== '');
+ if (hasText === arrowMode) return;
+ arrowMode = hasText;
+ arrowIndicators.forEach(ind => {
+ ind.classList.remove('fadeIn');
+ ind.classList.add('fadeOut');
+ setTimeout(() => {
+ if (hasText) {
+ ind.innerHTML = '';
+ ind.classList.add('arrow-mode');
+ } else {
+ ind.innerHTML = ind.dataset.original;
+ ind.classList.remove('arrow-mode');
+ }
+ ind.classList.remove('fadeOut');
+ ind.classList.add('fadeIn');
+ }, 100);
+ });
+ }
+
+ function triggerSubmit(input){
+ const query = input.value.trim();
+ if (!query) {
+ showToast('Please enter something in the Search Bar.','error','warning');
+ return;
}
+ if (window.APP && typeof APP.handleSearch === 'function') {
+ APP.handleSearch(query);
+ if (input.id === 'searchInput') input.value = '';
+ }
+ }
- document.addEventListener('keydown', function (e) {
- if (e.key === 'Escape') {
- const inputs = getSearchInputs();
- const active = document.activeElement;
- if (inputs.includes(active)) {
- active.blur();
- e.preventDefault();
- return;
- }
- }
+ function handleIndicatorAction(){
+ const inputs = getSearchInputs().filter(isVisible);
+ const active = document.activeElement;
+ if (inputs.includes(active) && active.value.trim()) {
+ triggerSubmit(active);
+ return;
+ }
+ const withText = inputs.find(i => i.value.trim());
+ if (withText) {
+ triggerSubmit(withText);
+ return;
+ }
+ focusFirstVisibleInput();
+ }
- if (e.ctrlKey && e.key.toLowerCase() === 's') {
- e.preventDefault();
- focusFirstVisibleInput();
- }
- });
+ updateIndicatorState();
+ getSearchInputs().forEach(i => i.addEventListener('input', updateIndicatorState));
- document.querySelectorAll(
- '.shortcut-indicator, .shortcut-indicator-2, .shortcut-indicator-3, .shortcut-indicator-4'
- ).forEach(function (el) {
- el.addEventListener('click', function (e) {
- e.preventDefault();
- focusFirstVisibleInput();
- });
- });
+ document.addEventListener('keydown', e => {
+ if (e.key === 'Escape') {
+ const act = document.activeElement;
+ if (getSearchInputs().includes(act)) {
+ act.blur();
+ e.preventDefault();
+ }
+ }
+ if (e.ctrlKey && e.key.toLowerCase() === 's') {
+ e.preventDefault();
+ focusFirstVisibleInput();
+ }
+ });
- document.body.addEventListener('click', function (e) {
- if (
- e.target.classList.contains('shortcut-indicator') ||
- e.target.classList.contains('shortcut-indicator-2') ||
- e.target.classList.contains('shortcut-indicator-3') ||
- e.target.classList.contains('shortcut-indicator-4')
- ) {
- e.preventDefault();
- focusFirstVisibleInput();
- }
- });
+ document.body.addEventListener('click', e => {
+ const ind = e.target.closest('.shortcut-indicator, .shortcut-indicator-2, .shortcut-indicator-3, .shortcut-indicator-4');
+ if (!ind) return;
+ e.preventDefault();
+ if (ind.classList.contains('arrow-mode')) {
+ handleIndicatorAction();
+ } else {
+ focusFirstVisibleInput();
+ }
+ });
- const coolIframe = document.getElementById('cool-iframe');
- if (coolIframe) {
- coolIframe.addEventListener('load', function () {
- const doc = coolIframe.contentWindow.document;
-
- doc.addEventListener('keydown', function (e) {
- if (e.key === 'Escape') {
- if (doc.activeElement && doc.activeElement.blur) {
- doc.activeElement.blur();
- e.preventDefault();
- return;
- }
- }
- if (e.ctrlKey && e.key.toLowerCase() === 's') {
- e.preventDefault();
- document.dispatchEvent(new KeyboardEvent('keydown', {
- key: 's',
- ctrlKey: true
- }));
- }
+ const coolIframe = document.getElementById('cool-iframe');
+ if (coolIframe){
+ coolIframe.addEventListener('load', () => {
+ const doc = coolIframe.contentWindow.document;
+ doc.addEventListener('keydown', innerE => {
+ if (innerE.key === 'Escape') {
+ if (doc.activeElement.blur) doc.activeElement.blur();
+ innerE.preventDefault();
+ }
+ if (innerE.ctrlKey && innerE.key.toLowerCase() === 's') {
+ innerE.preventDefault();
+ document.dispatchEvent(new KeyboardEvent('keydown', { key: 's', ctrlKey: true, bubbles: true }));
+ }
+ });
+ doc.querySelectorAll('.shortcut-indicator, .shortcut-indicator-2, .shortcut-indicator-3, .shortcut-indicator-4')
+ .forEach(el => {
+ el.addEventListener('click', ev => {
+ ev.preventDefault();
+ window.parent.postMessage({ type: 'iframe-focus-search' }, '*');
});
-
- doc.querySelectorAll(
- '.shortcut-indicator, .shortcut-indicator-2, .shortcut-indicator-3, .shortcut-indicator-4'
- ).forEach(function (iframeEl) {
- iframeEl.addEventListener('click', function (e) {
- e.preventDefault();
- window.parent.postMessage({
- type: 'iframe-focus-search'
- }, '*');
- });
- });
- });
- }
-
- window.addEventListener('message', function (event) {
- const msg = event.data;
- if (msg.type === 'iframe-focus-search') {
- focusFirstVisibleInput();
- }
+ });
});
- });
+ }
+
+ window.addEventListener('message', msgEvt => {
+ if (msgEvt.data?.type === 'iframe-focus-search'){
+ const inp = focusFirstVisibleInput();
+ if (inp && inp.value.trim()) triggerSubmit(inp);
+ }
+ });
+
+ });
})();
\ No newline at end of file
diff --git a/public/wah/cute2.js b/public/wah/cute2.js
index 144555f2..088a3ae3 100644
--- a/public/wah/cute2.js
+++ b/public/wah/cute2.js
@@ -1,367 +1,760 @@
"use strict";
+
(() => {
- const Ultraviolet = self.Ultraviolet;
- const REMOVE_HEADERS = [
- "cross-origin-embedder-policy",
- "cross-origin-opener-policy",
- "cross-origin-resource-policy",
- "content-security-policy",
- "content-security-policy-report-only",
- "expect-ct",
- "feature-policy",
- "origin-isolation",
- "strict-transport-security",
- "upgrade-insecure-requests",
- "x-content-type-options",
- "x-download-options",
- "x-frame-options",
- "x-permitted-cross-domain-policies",
- "x-powered-by",
- "x-xss-protection"
- ];
- const NO_BODY_METHODS = ["GET", "HEAD"];
- class UVServiceWorker extends Ultraviolet.EventEmitter {
- constructor(config = __uv$config) {
- super();
- config.prefix = config.prefix || "/wah/a/";
- this.config = config;
- this.bareClient = new Ultraviolet.BareClient();
- this.analyticsData = {};
- this.syncInterval = 300000;
- this.lastSync = Date.now();
- }
- route({ request }) {
- return request.url.startsWith(location.origin + this.config.prefix);
- }
- async fetch({ request }) {
- if (request.method.toUpperCase() === "OPTIONS") {
- return new Response(null, {
- status: 204,
- headers: {
- "Access-Control-Allow-Origin": "*",
- "Access-Control-Allow-Methods": "GET, HEAD, POST, OPTIONS",
- "Access-Control-Allow-Headers": "Content-Type, Authorization"
- }
- });
- }
- let requestUrl = "";
- try {
- if (!request.url.startsWith(location.origin + this.config.prefix))
- return await fetch(request);
- const uv = new Ultraviolet(this.config);
- if (typeof this.config.construct === "function")
- uv.construct(uv, "service");
- const blobPromise = NO_BODY_METHODS.includes(request.method.toUpperCase())
- ? Promise.resolve(null)
- : request.blob();
- const cookieDBPromise = uv.cookie.db();
- const [body, cookieDB] = await Promise.all([blobPromise, cookieDBPromise]);
- uv.meta.origin = location.origin;
- uv.meta.base = uv.meta.url = new URL(uv.sourceUrl(request.url));
- const reqWrapper = new UVRequestWrapper(request, uv, body);
- if (uv.meta.url.protocol === "blob:") {
- reqWrapper.blob = true;
- reqWrapper.base = reqWrapper.url = new URL(reqWrapper.url.pathname);
- }
- if (request.referrer && request.referrer.startsWith(location.origin)) {
- const refUrl = new URL(uv.sourceUrl(request.referrer));
- if (reqWrapper.headers.origin || (uv.meta.url.origin !== refUrl.origin && request.mode === "cors"))
- reqWrapper.headers.origin = refUrl.origin;
- delete reqWrapper.headers.referer;
- }
- const cookies = (await uv.cookie.getCookies(cookieDB)) || [];
- const cookieString = uv.cookie.serialize(cookies, uv.meta, false);
- reqWrapper.headers["user-agent"] = "SomethingSomething/1.0";
- if (cookieString) reqWrapper.headers.cookie = cookieString;
- const reqEvent = new InterceptionEvent(reqWrapper, null, null);
- this.emit("request", reqEvent);
- if (reqEvent.intercepted) return reqEvent.returnValue;
- requestUrl = reqWrapper.blob
- ? "blob:" + location.origin + reqWrapper.url.pathname
- : reqWrapper.url;
- const options = {
- headers: reqWrapper.headers,
- method: reqWrapper.method,
- body: reqWrapper.body,
- credentials: "include",
- mode: reqWrapper.mode,
- cache: reqWrapper.cache,
- redirect: reqWrapper.redirect
+ const Ultraviolet = self.Ultraviolet;
+
+ const REMOVE_HEADERS = [
+ "cross-origin-embedder-policy",
+ "cross-origin-opener-policy",
+ "cross-origin-resource-policy",
+ "content-security-policy",
+ "content-security-policy-report-only",
+ "expect-ct",
+ "feature-policy",
+ "origin-isolation",
+ "strict-transport-security",
+ "upgrade-insecure-requests",
+ "x-content-type-options",
+ "x-download-options",
+ "x-frame-options",
+ "x-permitted-cross-domain-policies",
+ "x-powered-by",
+ "x-xss-protection"
+ ];
+
+ const NO_BODY_METHODS = ["GET", "HEAD"];
+
+ const FP = `