From d2882efcb0f5082483106c8e016f1be6b84dfa6d Mon Sep 17 00:00:00 2001 From: Russell2259 Date: Thu, 21 Dec 2023 00:05:11 +0000 Subject: [PATCH] big push --- pages/404.html | 2 +- polaris.config.js | 4 +- server/index.js | 36 ++++---- server/utils/rewriter.js | 106 ++++++++++++++---------- static/apps.html | 4 +- static/assets/JSON/changelog.json | 4 +- static/assets/css/footer.css | 89 ++++++++++++++++++++ static/assets/css/main.css | 20 +++-- static/assets/js/apps.js | 9 +- static/assets/js/cheats.js | 2 +- static/assets/js/eastereggs.js | 2 +- static/assets/js/frame.js | 3 +- static/assets/js/games.js | 94 +++++++++------------ static/assets/js/main.js | 90 +++++++++----------- static/assets/js/page/game.js | 131 ++++++++++++++++++++++++++++++ static/assets/js/search.js | 7 +- static/assets/js/settings.js | 6 +- static/assets/js/themes.js | 51 +++++------- static/assets/js/utils.js | 72 ++++++++++++++++ static/assets/js/wpm.js | 7 -- static/cheats.html | 4 +- static/games.html | 12 +-- static/index.html | 1 + templates/adtop.html | 4 +- templates/footer.html | 31 +++++++ 25 files changed, 550 insertions(+), 241 deletions(-) create mode 100644 static/assets/css/footer.css create mode 100644 static/assets/js/page/game.js delete mode 100644 static/assets/js/wpm.js create mode 100644 templates/footer.html diff --git a/pages/404.html b/pages/404.html index 3024870..94ea1b9 100644 --- a/pages/404.html +++ b/pages/404.html @@ -15,7 +15,7 @@ -
+

404

diff --git a/polaris.config.js b/polaris.config.js index 4f918d0..fda6cdf 100644 --- a/polaris.config.js +++ b/polaris.config.js @@ -1,4 +1,4 @@ -import configTemplate from './polaris.config.template.js'; +import configTemplate from './polaris.config.template.js'; /** * @type {configTemplate} @@ -6,7 +6,7 @@ import configTemplate from './polaris.config.template.js'; export default { port: 8080, mode: 'dev', - minify: true, + minify: false, assetScrambling: true, allowDangerousTemplateInsert: true }; \ No newline at end of file diff --git a/server/index.js b/server/index.js index 3f91907..3996093 100644 --- a/server/index.js +++ b/server/index.js @@ -15,7 +15,7 @@ const app = express(); const server = http.createServer(); const bareServer = createBareServer('/bare/'); const mode = (process.argv[2] === 'prod' || process.argv[2] === 'dev' ? process.argv[2] : (process.argv[3] === 'prod' || process.argv[3] === 'dev' ? process.argv[3] : (config.mode === 'prod' || config.mode === 'dev' ? config.mode : 'prod'))); -const port = (process.argv[2] !== 'prod' && process.argv[2] !== 'dev' && Boolean(Number(process.argv[2]))) ? process.argv[2] : (Boolean(Number(process.argv[3])) ? process.argv[3] : (Boolean(Number(config.port)) ? config.port : (mode === 'prod' ? 80 : 8080 ) )); +const port = (process.argv[2] !== 'prod' && process.argv[2] !== 'dev' && Boolean(Number(process.argv[2]))) ? process.argv[2] : (Boolean(Number(process.argv[3])) ? process.argv[3] : (Boolean(Number(config.port)) ? config.port : (mode === 'prod' ? 80 : 8080))); const __dirname = url.fileURLToPath(new URL('.', import.meta.url)); app.get('/cdn/*', cors({ @@ -61,7 +61,7 @@ app.get('/asset/:token', async (req, res, next) => { TokenManager.delete(req.params.token); res.setHeader('content-type', token.data.type); - res.end(await rewriter.auto(fs.readFileSync(token.data.asset), token.data.type)); + res.end(await rewriter.auto(fs.readFileSync(token.data.asset), token.data.type, token.data.asset.replace(path.join(__dirname, '../static'), ''))); } else next(); } else next(); } @@ -73,21 +73,27 @@ app.get('/uv/service*', async (req, res) => { }); app.use(async (req, res, next) => { - const { - exists, - path: filePath - } = pathToFile(req.path, path.join(__dirname, '../static')); + if (req.path === '/index') res.redirect('/'); + else { + const { + exists, + path: filePath + } = pathToFile(req.path, path.join(__dirname, '../static')); - if (exists) { - res.setHeader('content-type', mime.getType(filePath)); + if (exists) { + if (req.path.endsWith('.html')) res.redirect(req.path.slice(0, -5)); + else { + res.setHeader('content-type', mime.getType(filePath)); - if (mime.getType(filePath) === 'text/html') res.end(await rewriter.html(fs.readFileSync(filePath))); - else if (mime.getType(filePath) === 'text/javascript') res.end(await rewriter.javascript(fs.readFileSync(filePath))); - else if (mime.getType(filePath) === 'text/css') res.end(await rewriter.css(fs.readFileSync(filePath))); - else res.sendFile(filePath); - } else { - res.setHeader('content-type', 'text/html'); - res.status(404).end(await rewriter.html(fs.readFileSync(path.join(__dirname, '../pages/404.html')))); + if (mime.getType(filePath) === 'text/html') res.end(await rewriter.html(fs.readFileSync(filePath), req.path)); + else if (mime.getType(filePath) === 'text/javascript') res.end(await rewriter.javascript(fs.readFileSync(filePath), req.path)); + else if (mime.getType(filePath) === 'text/css') res.end(await rewriter.css(fs.readFileSync(filePath), req.path)); + else res.sendFile(filePath); + } + } else { + res.setHeader('content-type', 'text/html'); + res.status(404).end(await rewriter.html(fs.readFileSync(path.join(__dirname, '../pages/404.html')))); + } } }); diff --git a/server/utils/rewriter.js b/server/utils/rewriter.js index e41114e..2695093 100644 --- a/server/utils/rewriter.js +++ b/server/utils/rewriter.js @@ -92,43 +92,54 @@ const html = (data) => { }); }; -const javascript = (data) => { +const javascript = (data, filePath) => { return new Promise((resolve, reject) => { const imports = String(data).split('import ') .map(data => data.split('from ')[1]) .filter(data => Boolean(data)) - .map(data => data.split(';')[0] + .map(data => data.split('\n')[0] .replaceAll('\'', '') .replaceAll('`', '') - .replaceAll('"', '')) - .filter(data => fs.existsSync(path.join(__dirname, '../templates', data + '.javascript'))); - + .replaceAll('"', '') + .replaceAll(';', '')) + .map(data => { + if (data.startsWith('./')) return { + originalFile: data, + newFile: path.join(filePath.split('/').slice(0, -1).join('/'), data) + }; + else if (data.startsWith('../')) return { + originalFile: data, + newFile: path.join(filePath.split('/').slice(0, -1).join('/'), data) + }; + else return { + originalFile: data, + newFile: data + }; + }) + .filter(data => fs.existsSync(path.join(__dirname, '../static', data.newFile))); let javascript = String(data); - if (config.assetScrambling) for (let i = 0; i < imports.length; i++) { - javascript = javascript.replace(imports[i], '/asset/' + TokenManager.generate('asset', 20000, { - asset: path.join(__dirname, '../static', imports[i]), - type: 'text/javascript' - }).token); - } + if (config.assetScrambling) for (let i = 0; i < imports.length; i++) javascript = javascript.replace(imports[i].originalFile, '/asset/' + TokenManager.generate('asset', 20000, { + asset: path.join(__dirname, '../static', imports[i].newFile), + type: 'text/javascript' + }).token); - if (config.minify) resolve(JavaScriptObfuscator.obfuscate(javascript, - { - compact: true, - controlFlowFlattening: true, - controlFlowFlatteningThreshold: 1, - numbersToExpressions: true, - simplify: true, - stringArrayShuffle: true, - splitStrings: true, - stringArrayThreshold: 1 - }).getObfuscatedCode()); + if (config.minify) resolve(JavaScriptObfuscator.obfuscate(javascript, { + compact: true, + controlFlowFlattening: true, + controlFlowFlatteningThreshold: 1, + numbersToExpressions: true, + simplify: true, + stringArrayShuffle: true, + splitStrings: true, + stringArrayThreshold: 1 + }).getObfuscatedCode()); else resolve(javascript); }); }; -const css = (data) => { +const css = (data, filePath) => { return new Promise((resolve, reject) => { const imports = String(data).split('url(') .map(data => { @@ -143,37 +154,48 @@ const css = (data) => { else return undefined; }) .filter(data => { - if (data) { - try { - new URL(data); + if (data) try { + new URL(data); - return false; - } catch (e) { - if (data.startsWith('/')) return true; - else return false; - } + return false; + } catch (e) { + return true; } else return false; }) - .filter(data => fs.existsSync(path.join(__dirname, '../templates', data + mime.getExtension(data)))); + .map(data => { + // console.log(path.join(filePath.split('/').slice(0, -1).join('/'))); + + if (data.startsWith('./')) return { + originalFile: data, + newFile: path.join(filePath.split('/').slice(0, -1).join('/'), data) + }; + else if (data.startsWith('../')) return { + originalFile: data, + newFile: path.join(filePath.split('/').slice(0, -1).join('/'), data) + }; + else return { + originalFile: data, + newFile: data + }; + }) + .filter(data => fs.existsSync(path.join(__dirname, '../static', data.newFile))); let css = String(data); - if (config.assetScrambling) for (let i = 0; i < imports.length; i++) { - css = css.replace(imports[i], '/asset/' + TokenManager.generate('asset', 20000, { - asset: path.join(__dirname, '../static', imports[i]), - type: mime.getType(path.join(__dirname, '../static', imports[i])) - }).token); - } - + if (config.assetScrambling) for (let i = 0; i < imports.length; i++) css = css.replace(imports[i].originalFile, '/asset/' + TokenManager.generate('asset', 20000, { + asset: path.join(__dirname, '../static', imports[i].newFile), + type: mime.getType(path.join(__dirname, '../static', imports[i].newFile)) + }).token); + if (config.minify) resolve(css.replace(/(\r\n|\n|\r)/gm, '').replaceAll(' ', ' ')); else resolve(css); }); }; -const auto = async (data, type) => { +const auto = async (data, type, filePath) => { if (type === 'text/html') return await html(data); - else if (type === 'text/javascript' || type === 'application/javascript') return await javascript(data); - else if (type === 'text/css') return await css(data); + else if (type === 'text/javascript' || type === 'application/javascript') return await javascript(data, filePath); + else if (type === 'text/css') return await css(data, filePath); else return data; }; diff --git a/static/apps.html b/static/apps.html index 963ca2d..ecedb57 100644 --- a/static/apps.html +++ b/static/apps.html @@ -15,12 +15,14 @@ -

+

Apps


+ + diff --git a/static/assets/JSON/changelog.json b/static/assets/JSON/changelog.json index a94e214..73f9ee7 100644 --- a/static/assets/JSON/changelog.json +++ b/static/assets/JSON/changelog.json @@ -1,7 +1,7 @@ [ { - "date": "some/time/2023?", - "simpleDescription": "Version 1.2 Release" + "date": "1/1/2024", + "simpleDescription": "2024 Update!!!" }, { "date": "11/23/2023", diff --git a/static/assets/css/footer.css b/static/assets/css/footer.css new file mode 100644 index 0000000..8d4ecf7 --- /dev/null +++ b/static/assets/css/footer.css @@ -0,0 +1,89 @@ +footer { + position: relative; + text-align: left; + background-image: url('/assets/img/background.jpeg'); + background-attachment: fixed; + background-position: center; + background-repeat: no-repeat; + background-size: cover; + user-select: none; + padding: 4% 5% 2% 5%; + color: #fff; + margin-top: 50px; + text-shadow: 0px 0px 20px rgba(0, 0, 0, 0.616); +} + +footer p { + text-shadow: 0px 0px 20px rgba(0, 0, 0, 0.616); +} + +footer h1 { + font-family: 'Lato-Black'; + color: #fff; + margin: 0px; + margin-bottom: 10px; +} + +footer::before { + display: block; + content: ''; + height: 270px; + position: fixed; + bottom: 0; + left: 0; + width: 100vw; + z-index: -1; + background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(0, 0, 0, 0.8) 100%); +} + +footer .socials { + margin-bottom: 20px; +} + +footer .socials i { + margin: 10px; + margin-left: 5px; + margin-right: 5px; + font-size: 20px; + cursor: pointer; +} + +footer .socials a { + color: #fff; +} + +footer .socials a:hover { + color: #fff; +} + +footer .socials a::before { + display: none; +} + +footer .socials i:is(:first-child) { + margin-left: 0px; +} + +footer .right { + position: absolute; + right: 5%; + text-align: right; +} + +footer .right a { + display: block; + margin-top: 20px; +} + +footer .title:not(:last-child) { + display: flex; + margin: 0px; +} + +footer .title img { + width: 40px; + height: 40px; + margin-left: 10px; + filter: drop-shadow(0px 0px 20px rgba(0, 0, 0, 0.616)); + border-radius: 1vh; +} \ No newline at end of file diff --git a/static/assets/css/main.css b/static/assets/css/main.css index 4f56977..4599427 100644 --- a/static/assets/css/main.css +++ b/static/assets/css/main.css @@ -1,9 +1,10 @@ @import url('https://site-assets.fontawesome.com/releases/v6.2.0/css/all.css'); -@import url('/assets/css/fonts.css'); -@import url('/assets/css/themes.css'); -@import url('/assets/css/nav.css'); -@import url('/assets/css/sidebar.css'); -@import url('/assets/css/dropdown.css'); +@import url('./fonts.css'); +@import url('./themes.css'); +@import url('./nav.css'); +@import url('./sidebar.css'); +@import url('./dropdown.css'); +@import url('./footer.css'); * { font-family: 'Lato'; @@ -21,6 +22,10 @@ body { background-repeat: no-repeat; } +.centered { + text-align: center; +} + html { min-height: 100%; } @@ -517,6 +522,11 @@ img.featured:hover { transition: border 0.5s linear; } +.content { + margin-left: 100px; + margin-right: 100px; +} + @keyframes beat { 0%, 50%, diff --git a/static/assets/js/apps.js b/static/assets/js/apps.js index 6b1146e..0659851 100644 --- a/static/assets/js/apps.js +++ b/static/assets/js/apps.js @@ -1,5 +1,5 @@ -import PolarisError from '/assets/js/error.js'; -import { loadWorker } from '/assets/js/wpm.js'; +import { loadProxyWorker } from './utils.js'; +import PolarisError from './error.js'; const tiltEffectSettings = { max: 8, @@ -18,7 +18,8 @@ const load = () => { document.querySelector('.apps').appendChild(el); el.addEventListener('click', async () => { - await loadWorker('uv'); + await loadProxyWorker('uv'); + localStorage.setItem('frameData', JSON.stringify({ type: 'app', app @@ -67,4 +68,4 @@ function setTransition(event) { export default { load -}; +}; \ No newline at end of file diff --git a/static/assets/js/cheats.js b/static/assets/js/cheats.js index 12c9388..0925126 100644 --- a/static/assets/js/cheats.js +++ b/static/assets/js/cheats.js @@ -1,4 +1,4 @@ -import PolarisError from '/assets/js/error.js'; +import PolarisError from './error.js'; const tiltEffectSettings = { max: 8, diff --git a/static/assets/js/eastereggs.js b/static/assets/js/eastereggs.js index d8a38e0..57db5c2 100644 --- a/static/assets/js/eastereggs.js +++ b/static/assets/js/eastereggs.js @@ -161,7 +161,7 @@ easterEggs.push({ font-size: 5.5vh; left: 50%; -ms-transform: translate(-50%); - transform: translate(-50%);">Hamster`; + transform: translate(-50%);">Hamter`; menu.appendChild(caller); const call = document.createElement('div'); diff --git a/static/assets/js/frame.js b/static/assets/js/frame.js index e901ee7..3c7ac1a 100644 --- a/static/assets/js/frame.js +++ b/static/assets/js/frame.js @@ -1,6 +1,5 @@ const load = () => { let frameData = JSON.parse(localStorage.getItem('frameData')); - if (!frameData) location.href = '/'; const iframe = document.querySelector('.frame'); @@ -29,7 +28,7 @@ const load = () => { document.querySelector('#gameicon').src = "https://cdn3.iconfinder.com/data/icons/feather-5/24/search-512.png"; document.querySelector('#gametitle').textContent = "Proxy"; } else document.querySelector('#gametitle').textContent = 'Failed to load proxy.'; - } else location.href = '/'; + } document.querySelector('#fullscreen').addEventListener('click', () => { const iframe = document.querySelector('.frame'); diff --git a/static/assets/js/games.js b/static/assets/js/games.js index 74c7807..8ef809c 100644 --- a/static/assets/js/games.js +++ b/static/assets/js/games.js @@ -1,31 +1,28 @@ -import PolarisError from './error.js'; -import { workerLoaded, loadWorker } from './wpm.js'; +import PolarisError from '/assets/js/error.js'; +import { loadProxyWorker } from '/assets/js/utils.js'; const tiltEffectSettings = { - max: 8, // max tilt rotation (degrees (deg)) - perspective: 1000, // transform perspective, the lower the more extreme the tilt gets (pixels (px)) - scale: 1.05, // transform scale - 2 = 200%, 1.5 = 150%, etc.. - speed: 800, // speed (transition-duration) of the enter/exit transition (milliseconds (ms)) - easing: 'cubic-bezier(.03,.98,.52,.99)' // easing (transition-timing-function) of the enter/exit transition + max: 8, + perspective: 1000, + scale: 1.05, + speed: 800, + easing: 'cubic-bezier(.03,.98,.52,.99)' }; -let games = []; // store all games -let filteredGames = []; // store filtered games +let games = []; +let filteredGames = []; const load = () => { fetch('/assets/JSON/games.json').then(res => res.json()).then(data => { games = data; - filteredGames = games; // initialize filtered games with all games + filteredGames = games; - renderGames(filteredGames); // render games initially + renderGames(filteredGames); - // Add event listener to search input const searchInput = document.getElementById('searchInput'); searchInput.addEventListener('input', filterGames); }) - .catch(e => { - new PolarisError('Failed to load games'); - }); + .catch(e => new PolarisError('Failed to load games')); }; function filterGames() { @@ -34,20 +31,14 @@ function filterGames() { filteredGames = games.filter(game => game.name.toLowerCase().includes(searchTerm)); - renderGames(filteredGames); // render filtered games + renderGames(filteredGames); } function renderGames(gamesToRender) { const gamesContainer = document.querySelector('.games'); const popularGamesContainer = document.querySelector('.popular-games'); - gamesContainer.innerHTML = ''; // clear previous games - popularGamesContainer.innerHTML = ''; // clear previous popular games - - function openGameInNewTab(game) { - const x = window.open('about:blank', '_blank'); - const index = game.source; - x.document.write(``); -} + gamesContainer.innerHTML = ''; + popularGamesContainer.innerHTML = ''; gamesToRender.forEach(game => { const el = document.createElement('div'); @@ -62,20 +53,15 @@ function renderGames(gamesToRender) { popularGamesContainer.appendChild(popularEl); popularEl.addEventListener('click', async () => { - if (!workerLoaded) await loadWorker(); - const frameData = { - type: 'game', - game - }; - if (game.openinnewtab === 'yes') { - window.open(game.source, '_blank'); - console.log('Open game in new tab:', frameData); - } else if (game.openinaboutblank === 'yes') { - openGameInNewTab(game); - console.log('Open game in about:blank:', frameData); - } else { - localStorage.setItem('frameData', JSON.stringify(frameData)); - location.href = '/view'; + await loadProxyWorker('uv'); + + if (game.openinnewtab === 'yes') window.open(game.source); + else { + localStorage.setItem('frameData', JSON.stringify({ + type: 'game', + game + })); + location.href = '/view'; } }); @@ -85,21 +71,20 @@ function renderGames(gamesToRender) { } el.addEventListener('click', async () => { - if (!workerLoaded) await loadWorker(); + await loadProxyWorker(); + const frameData = { type: 'game', game }; + if (game.openinnewtab === 'yes') { - window.open(game.source, '_blank'); - console.log('Open game in new tab:', frameData); - } else if (game.openinaboutblank === 'yes') { - openGameInNewTab(game); - console.log('Open game in about:blank:', frameData); - } else { - localStorage.setItem('frameData', JSON.stringify(frameData)); - location.href = '/view'; - } + window.open(game.source, '_blank'); + console.log('Open game in new tab:', frameData); + } else { + localStorage.setItem('frameData', JSON.stringify(frameData)); + location.href = '/view'; + } }); el.addEventListener('mouseenter', gameMouseEnter); @@ -122,10 +107,8 @@ function gameMouseMove(event) { const mouseY = event.clientY - centerY; const rotateXUncapped = (+1) * tiltEffectSettings.max * mouseY / (gameHeight / 2); const rotateYUncapped = (-1) * tiltEffectSettings.max * mouseX / (gameWidth / 2); - const rotateX = rotateXUncapped < -tiltEffectSettings.max ? -tiltEffectSettings.max : - (rotateXUncapped > tiltEffectSettings.max ? tiltEffectSettings.max : rotateXUncapped); - const rotateY = rotateYUncapped < -tiltEffectSettings.max ? -tiltEffectSettings.max : - (rotateYUncapped > tiltEffectSettings.max ? tiltEffectSettings.max : rotateYUncapped); + const rotateX = rotateXUncapped < -tiltEffectSettings.max ? -tiltEffectSettings.max : (rotateXUncapped > tiltEffectSettings.max ? tiltEffectSettings.max : rotateXUncapped); + const rotateY = rotateYUncapped < -tiltEffectSettings.max ? -tiltEffectSettings.max : (rotateYUncapped > tiltEffectSettings.max ? tiltEffectSettings.max : rotateYUncapped); game.style.transform = `perspective(${tiltEffectSettings.perspective}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(${tiltEffectSettings.scale}, ${tiltEffectSettings.scale}, ${tiltEffectSettings.scale})`; } @@ -139,11 +122,10 @@ function setTransition(event) { const game = event.currentTarget; clearTimeout(game.transitionTimeoutId); game.style.transition = `transform ${tiltEffectSettings.speed}ms ${tiltEffectSettings.easing}`; - game.transitionTimeoutId = setTimeout(() => { - game.style.transition = ''; - }, tiltEffectSettings.speed); + + game.transitionTimeoutId = setTimeout(() => game.style.transition = '', tiltEffectSettings.speed); } export default { load -}; +}; \ No newline at end of file diff --git a/static/assets/js/main.js b/static/assets/js/main.js index 9e38fcc..895236b 100644 --- a/static/assets/js/main.js +++ b/static/assets/js/main.js @@ -1,15 +1,13 @@ -// Don't touch -import { load } from './settings.js'; -import Games from './games.js'; -import Apps from './apps.js'; +import loadEasterEggs from './eastereggs.js'; +import PolarisError from './error.js'; +import Settings from './settings.js'; import Search from './search.js'; import Cheats from './cheats.js'; +import Games from './games.js'; import Frame from './frame.js'; -import PolarisError from './error.js'; +import Apps from './apps.js'; -const Settings = { - load: load -}; +loadEasterEggs(); onbeforeunload = (e) => { if (localStorage.getItem('prevent_close') === 'true') { @@ -25,62 +23,52 @@ window.onhashchange = () => { else document.querySelector('.sidebar').classList.remove('active'); }; -if (window.self === window.top) { - setTimeout(async () => { - Settings.load(); +if (window.self === window.top) setTimeout(async () => { + Settings.load(); - if (location.pathname === '/games') Games.load(); - if (location.pathname === '/apps') Apps.load(); - if (location.pathname === '/search') Search.load(); - if (location.pathname === '/cheats') Cheats.load(); - if (location.pathname === '/view') Frame.load(); - }, 500); -} + if (location.pathname === '/games') Games.load(); + if (location.pathname === '/apps') Apps.load(); + if (location.pathname === '/search') Search.load(); + if (location.pathname === '/cheats') Cheats.load(); + if (location.pathname === '/view') Frame.load(); +}, 500); if (location.pathname === '/') { fetch('/assets/JSON/games.json').then(res => res.json()).then(games => { const gameName = 'Tiny Fishing'; const game = games.filter(g => g.name === gameName)[0]; - document.querySelector('.featuredimg').addEventListener('click', () => { + document.querySelector('.featured').addEventListener('click', () => { localStorage.setItem('frameData', JSON.stringify({ type: 'game', game })); - + location.href = '/view'; }); - document.querySelector('.featuredimg').src = '/assets/img/wide/tinyfishing.png'; + document.querySelector('.featured').src = '/assets/img/wide/tinyfishing.png'; }).catch(e => new PolarisError('Failed to load featured game.')); - - fetch('/assets/JSON/changelog.json').then(res => res.json()).then(changelog => changelog.forEach(change => { - const date = document.createElement('p'); - date.textContent = change.date; - date.classList = 'small'; - document.querySelector('#changelog').appendChild(date); - - const descwrap = document.createElement('p'); + + fetch('/assets/JSON/changelog.json').then(res => res.json()).then(changelog => changelog.forEach(change => { + const date = document.createElement('p'); + date.textContent = change.date; + date.classList = 'small'; + document.querySelector('#changelog').appendChild(date); + + const descwrap = document.createElement('p'); const description = document.createElement('i'); - description.textContent = change.simpleDescription; - description.classList = 'small'; - document.querySelector('#changelog').appendChild(description); - })); -/* -var items = ['the start', 'What are you doing here?', '"School"', 'I dont get paid enough','What Up Son?','help','i like bagle','3.14159265359','Who thought this was a good idea?','Stage 4','i have a concerning lump on my back','Bean was here','Your Mother','Pacer Test','Why did he leave','by the way...','Kilroy was here','Kilroy is here','look behind you','West Virginia','theres a reason','Country road','Thats a wrap','Pretty','No','Yes','leave me','What square?','uhhh','Plutocracy','Practically Free*','capitalize this','Place Holder','Try me','fine','Why are we doing this again?','half eaten saltine crackers are underated','Javascript > Java','L + Ratio','Cope','I Love Refrigerators','That Happened.','Pedicure','(insert message here)','terminal','💀💀💀','finnish','who writes these?','reference','I am going to peel the skin off your face (:','bye','no','the fact is','run','uh what','hello world','Positively awful','tax fraud','comatose state','Not me','my second job is a discord mod','kids bop','Is it just me or','Hello people','74% Incomplete','wake up','Monster Energy','ew','The amount of pain I am in right now is unimaginable','chicken','men','What?','Your opinion is invalid','gay pride','Im going','4skin','/0','Who said that?','No Fair.','Famous... Enough','Parent Approved!','Teacher Approved!','Treason','Just do it already!','You\'re Fired','Not worth it','was there a reason?','the egg came first','patriotism','Family Friendly','Do you ever feel like a plastic bag Drifting through the windWanting to start again? Do you ever feel, feel so paper thin Like a house of cards One blow from caving in?','Why?','discord is in the first o','Shane Dawson likes cats','who stole this','unblock linux','darn you','gushers','yummy','charles loves you','mekhi loves anime', 'pls dont type smurf :)']; - - function getRandomFact() { - var randomIndex = Math.floor(Math.random() * items.length); - return items[randomIndex]; - } - - // When the page loads, set the innerHTML of elements with class 'blue' to a random item - window.addEventListener('load', function() { - var blue = document.getElementsByClassName('blue'); - for (var i = 0; i < blue.length; i++) { - blue[i].innerHTML = getRandomFact(); - } - }); -*/ + description.textContent = change.simpleDescription; + description.classList = 'small'; + document.querySelector('#changelog').appendChild(description); + })); } -const Polaris = { Settings, Games, Apps, Frame, PolarisError }; -export default Polaris; \ No newline at end of file + +if (window.scrollY !== 0) document.querySelector('.navbar').classList.add('scrolling'); +else document.querySelector('.navbar').classList.remove('scrolling'); + +window.onscroll = () => { + if (window.scrollY !== 0) document.querySelector('.navbar').classList.add('scrolling'); + else document.querySelector('.navbar').classList.remove('scrolling'); +} + +export default { Settings, Games, Apps, Frame, PolarisError }; \ No newline at end of file diff --git a/static/assets/js/page/game.js b/static/assets/js/page/game.js new file mode 100644 index 0000000..8ef809c --- /dev/null +++ b/static/assets/js/page/game.js @@ -0,0 +1,131 @@ +import PolarisError from '/assets/js/error.js'; +import { loadProxyWorker } from '/assets/js/utils.js'; + +const tiltEffectSettings = { + max: 8, + perspective: 1000, + scale: 1.05, + speed: 800, + easing: 'cubic-bezier(.03,.98,.52,.99)' +}; + +let games = []; +let filteredGames = []; + +const load = () => { + fetch('/assets/JSON/games.json').then(res => res.json()).then(data => { + games = data; + filteredGames = games; + + renderGames(filteredGames); + + const searchInput = document.getElementById('searchInput'); + searchInput.addEventListener('input', filterGames); + }) + .catch(e => new PolarisError('Failed to load games')); +}; + +function filterGames() { + const searchInput = document.getElementById('searchInput'); + const searchTerm = searchInput.value.toLowerCase(); + + filteredGames = games.filter(game => game.name.toLowerCase().includes(searchTerm)); + + renderGames(filteredGames); +} + +function renderGames(gamesToRender) { + const gamesContainer = document.querySelector('.games'); + const popularGamesContainer = document.querySelector('.popular-games'); + gamesContainer.innerHTML = ''; + popularGamesContainer.innerHTML = ''; + + gamesToRender.forEach(game => { + const el = document.createElement('div'); + el.classList = 'game'; + el.innerHTML = `

${game.name}

`; + gamesContainer.appendChild(el); + + if (game.popular === 'yes') { + const popularEl = document.createElement('div'); + popularEl.classList = 'game'; + popularEl.innerHTML = `

${game.name}

`; + popularGamesContainer.appendChild(popularEl); + + popularEl.addEventListener('click', async () => { + await loadProxyWorker('uv'); + + if (game.openinnewtab === 'yes') window.open(game.source); + else { + localStorage.setItem('frameData', JSON.stringify({ + type: 'game', + game + })); + location.href = '/view'; + } + }); + + popularEl.addEventListener('mouseenter', gameMouseEnter); + popularEl.addEventListener('mousemove', gameMouseMove); + popularEl.addEventListener('mouseleave', gameMouseLeave); + } + + el.addEventListener('click', async () => { + await loadProxyWorker(); + + const frameData = { + type: 'game', + game + }; + + if (game.openinnewtab === 'yes') { + window.open(game.source, '_blank'); + console.log('Open game in new tab:', frameData); + } else { + localStorage.setItem('frameData', JSON.stringify(frameData)); + location.href = '/view'; + } + }); + + el.addEventListener('mouseenter', gameMouseEnter); + el.addEventListener('mousemove', gameMouseMove); + el.addEventListener('mouseleave', gameMouseLeave); + }); +} + +function gameMouseEnter(event) { + setTransition(event); +} + +function gameMouseMove(event) { + const game = event.currentTarget; + const gameWidth = game.offsetWidth; + const gameHeight = game.offsetHeight; + const centerX = game.offsetLeft + gameWidth / 2; + const centerY = game.offsetTop + gameHeight / 2; + const mouseX = event.clientX - centerX; + const mouseY = event.clientY - centerY; + const rotateXUncapped = (+1) * tiltEffectSettings.max * mouseY / (gameHeight / 2); + const rotateYUncapped = (-1) * tiltEffectSettings.max * mouseX / (gameWidth / 2); + const rotateX = rotateXUncapped < -tiltEffectSettings.max ? -tiltEffectSettings.max : (rotateXUncapped > tiltEffectSettings.max ? tiltEffectSettings.max : rotateXUncapped); + const rotateY = rotateYUncapped < -tiltEffectSettings.max ? -tiltEffectSettings.max : (rotateYUncapped > tiltEffectSettings.max ? tiltEffectSettings.max : rotateYUncapped); + + game.style.transform = `perspective(${tiltEffectSettings.perspective}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(${tiltEffectSettings.scale}, ${tiltEffectSettings.scale}, ${tiltEffectSettings.scale})`; +} + +function gameMouseLeave(event) { + event.currentTarget.style.transform = `perspective(${tiltEffectSettings.perspective}px) rotateX(0deg) rotateY(0deg) scale3d(1, 1, 1)`; + setTransition(event); +} + +function setTransition(event) { + const game = event.currentTarget; + clearTimeout(game.transitionTimeoutId); + game.style.transition = `transform ${tiltEffectSettings.speed}ms ${tiltEffectSettings.easing}`; + + game.transitionTimeoutId = setTimeout(() => game.style.transition = '', tiltEffectSettings.speed); +} + +export default { + load +}; \ No newline at end of file diff --git a/static/assets/js/search.js b/static/assets/js/search.js index 6ecb3ae..5d713e2 100644 --- a/static/assets/js/search.js +++ b/static/assets/js/search.js @@ -1,5 +1,5 @@ -import PolarisError from '/assets/js/error.js'; -import { loadWorker } from '/assets/js/wpm.js'; +import PolarisError from './error.js'; +import { loadProxyWorker } from './utils.js'; const load = () => { const xor = { @@ -20,7 +20,7 @@ const load = () => { e.preventDefault(); if (typeof navigator.serviceWorker === 'undefined') new PolarisError('Failed to load Proxy'); - await loadWorker('uv'); + await loadProxyWorker('uv'); const url = /^(http(s)?:\/\/)?([\w-]+\.)+[\w]{2,}(\/.*)?$/.test(query.value) ? ((!query.value.startsWith('http://') && !query.value.startsWith('https://')) ? 'https://' + query.value : query.value) : 'https://www.google.com/search?q=' + encodeURIComponent(query.value); @@ -28,6 +28,7 @@ const load = () => { type: 'proxy', source: `/uv/service/${xor.encode(url)}` })); + location.href = '/view'; }); } diff --git a/static/assets/js/settings.js b/static/assets/js/settings.js index a5f4a67..426538e 100644 --- a/static/assets/js/settings.js +++ b/static/assets/js/settings.js @@ -1,5 +1,5 @@ -import PolarisError from '/assets/js/error.js'; -import Theme from '/assets/js/themes.js'; +import PolarisError from './error.js'; +import Theme from './themes.js'; const isScrollable = (element) => element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight; @@ -205,4 +205,4 @@ const load = () => { new Settings(); }; -export { load, Settings }; +export default { load, Settings }; diff --git a/static/assets/js/themes.js b/static/assets/js/themes.js index 4b3a6c8..f65528b 100644 --- a/static/assets/js/themes.js +++ b/static/assets/js/themes.js @@ -1,47 +1,34 @@ -const set = (name, value) => { - if (!localStorage.getItem('settings')) { - localStorage.setItem('settings', JSON.stringify({})); - } else { - try { - JSON.parse(localStorage.getItem('settings')); - } catch (e) { - localStorage.setItem('settings', JSON.stringify({})); - } - } +import { storage } from './utils.js'; - const settings = JSON.parse(localStorage.getItem('settings')); - settings[name] = value; - localStorage.setItem('settings', JSON.stringify(settings)); -}; - -const get = (name) => { - if (!localStorage.getItem('settings')) { - localStorage.setItem('settings', JSON.stringify({})); - } else { - try { - JSON.parse(localStorage.getItem('settings')); - } catch (e) { - localStorage.setItem('settings', JSON.stringify({})); - } - } - - const settings = JSON.parse(localStorage.getItem('settings')); - return settings[name]; -} +const settingsStorage = storage('settings'); class Theme { constructor() { - this.theme = get('theme'); + this.theme = settingsStorage.get('theme'); if (this.theme) this.set(this.theme); else this.set('system-default'); } + /** + * Set the theme of the page + * @param {string} theme The name of the theme + * @param {boolean} save Whether or not the theme should be saved + */ set = (theme, save) => { document.body.setAttribute('data-theme', theme); + this.theme = theme; - if (save !== false) set('theme', theme); - } + if (save !== false) settingsStorage.set('theme', theme); + }; + + /** + * Get the current theme + * @returns {string} + */ + get = () => { + return document.body.getAttribute('data-theme'); + }; } export default new Theme(); \ No newline at end of file diff --git a/static/assets/js/utils.js b/static/assets/js/utils.js index e69de29..e16461b 100644 --- a/static/assets/js/utils.js +++ b/static/assets/js/utils.js @@ -0,0 +1,72 @@ +/** + * The storage interface for polaris + * @param {string} containerName + */ +const storage = (containerName) => { + return { + /** + * Get a value from the storage container + * @param {string} name The name of the value + * @returns {string} + */ + get: (name) => { + if (!localStorage.getItem(containerName)) localStorage.setItem(containerName, JSON.stringify({})); + else { + try { + JSON.parse(localStorage.getItem(containerName)); + } catch (e) { + localStorage.setItem(containerName, JSON.stringify({})); + } + } + + const container = JSON.parse(localStorage.getItem(containerName)); + return container[name]; + }, + /** + * Set a value from a storage container + * @param {string} name The name of the value + * @param {string | object} value The value to be set + */ + set: (name, value) => { + if (!localStorage.getItem(containerName)) localStorage.setItem(containerName, JSON.stringify({})); + else { + try { + JSON.parse(localStorage.getItem(containerName)); + } catch (e) { + localStorage.setItem(containerName, JSON.stringify({})); + } + } + + const container = JSON.parse(localStorage.getItem(containerName)); + container[name] = value; + + localStorage.setItem(containerName, JSON.stringify(container)); + } + }; +}; + +/** + * Register a proxy service worker + * @param {'uv' | 'dynamic'} proxy + */ +const loadProxyWorker = async (proxy) => await navigator.serviceWorker.register(`/${proxy}/sw.js`, { + scope: `/${proxy}/service/` +}); + +/** + * Load the page javascript + */ +const loadPageScript = () => { + if (location.href) { + + } +}; + +export default { + storage, + loadProxyWorker +}; +export { + storage, + loadProxyWorker +}; \ No newline at end of file diff --git a/static/assets/js/wpm.js b/static/assets/js/wpm.js deleted file mode 100644 index 40a5277..0000000 --- a/static/assets/js/wpm.js +++ /dev/null @@ -1,7 +0,0 @@ -const loadWorker = async (proxy) => await navigator.serviceWorker.register(`/${proxy}/sw.js`, { - scope: `/${proxy}/service/`, -}); - -export { - loadWorker -}; diff --git a/static/cheats.html b/static/cheats.html index 298a9c9..cb6dff4 100644 --- a/static/cheats.html +++ b/static/cheats.html @@ -11,7 +11,7 @@ Cheats | Polaris - + @@ -21,6 +21,8 @@
+ + diff --git a/static/games.html b/static/games.html index d70a031..782aada 100644 --- a/static/games.html +++ b/static/games.html @@ -15,7 +15,7 @@ -
+

Games

Popular

@@ -27,18 +27,10 @@ -
- -
-
- -
-
-
-
+ diff --git a/static/index.html b/static/index.html index 2ad5771..064fca2 100644 --- a/static/index.html +++ b/static/index.html @@ -36,6 +36,7 @@ - Terms of Service

+

Changelog

diff --git a/templates/adtop.html b/templates/adtop.html index a163a99..093dee2 100644 --- a/templates/adtop.html +++ b/templates/adtop.html @@ -1,3 +1,3 @@ - - \ No newline at end of file + + \ No newline at end of file diff --git a/templates/footer.html b/templates/footer.html new file mode 100644 index 0000000..40c1509 --- /dev/null +++ b/templates/footer.html @@ -0,0 +1,31 @@ + \ No newline at end of file