sync
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import config from '../polaris.config.js';
|
||||
|
||||
import childProcess from 'node:child_process';
|
||||
import path from 'node:path';
|
||||
import url from 'node:url';
|
||||
@@ -6,6 +8,7 @@ import fs from 'node:fs';
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
|
||||
const packageFile = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json')));
|
||||
const commits = await (await fetch(`https://api.github.com/repos/Skoolgq/Polaris/commits`)).json();
|
||||
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')));
|
||||
var gitSupported = true;
|
||||
|
||||
/**
|
||||
@@ -39,6 +42,8 @@ const routes = (app) => {
|
||||
upToDate: false
|
||||
};
|
||||
|
||||
changelog.mode = mode === 'dev' ? 'development' : 'production';
|
||||
|
||||
res.json(changelog);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
[
|
||||
{
|
||||
"date": "1/16/2024",
|
||||
"simpleDescription": "Changed featured game to Retro Bowl"
|
||||
},
|
||||
{
|
||||
"date": "1/15/2024",
|
||||
"simpleDescription": "Updated Privacy Policy + TOS"
|
||||
|
||||
@@ -442,13 +442,13 @@
|
||||
},
|
||||
{
|
||||
"name": "Smash Karts",
|
||||
"target": "//smartcart1.github.io/s/smash-karts/",
|
||||
"target": "https://smartcart1.github.io/s/smash-karts/",
|
||||
"image": "https://img.gamepix.com/games/smash-karts/icon/smash-karts.png"
|
||||
},
|
||||
{
|
||||
"name": "Snow Rider 3D",
|
||||
"target": "https://23azostore.github.io/s8/snow-rider-3d/",
|
||||
"image": "https://img.gamepix.com/games/smash-karts/icon/smash-karts.png"
|
||||
"image": "https://img.gamepix.com/games/snow-rider-3d/cover/snow-rider-3d.png?width=600&height=340&fit=cover&quality=90"
|
||||
},
|
||||
{
|
||||
"name": "Soccer Random",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
@@ -6,6 +6,7 @@ fetch('/api/changelog')
|
||||
document.querySelector('#changelog_version').textContent = changelog.version !== 'unknown' ? 'v' + changelog.version : changelog.version;
|
||||
document.querySelector('#changelog_version_sha').textContent = changelog.commit.sha.slice(0, 7);
|
||||
document.querySelector('#changelog_up_to_date').textContent = changelog.upToDate ? 'yes' : 'no';
|
||||
document.querySelector('#changelog_mode').textContent = changelog.mode;
|
||||
|
||||
changelog.changelog
|
||||
.forEach(change => {
|
||||
|
||||
@@ -7,6 +7,8 @@ const load = () => {
|
||||
.then(games => {
|
||||
const searchBar = document.querySelector('#searchInput');
|
||||
|
||||
searchBar.setAttribute('placeholder', `Search ${games.all.length} Games`);
|
||||
|
||||
searchBar.addEventListener('input', () => {
|
||||
console.log(searchBar.value);
|
||||
|
||||
|
||||
+18
-12
@@ -1,11 +1,12 @@
|
||||
import { createViewPage, isValidURL, getVH, CrossTabCommunication, PolarisError } from './utils.js';
|
||||
import { loadSettings, loadSidebarInterface } from './settings.js';
|
||||
import loadEasterEggs from './eastereggs.js';
|
||||
import Settings from './settings.js';
|
||||
import Search from './search.js';
|
||||
import Cheats from './cheats.js';
|
||||
import Games from './games.js';
|
||||
import Apps from './apps.js';
|
||||
|
||||
if (location.pathname !== '/view') loadSidebarInterface();
|
||||
loadEasterEggs();
|
||||
|
||||
/*const ctcClient = new CrossTabCommunication();
|
||||
@@ -25,7 +26,7 @@ onbeforeunload = (e) => {
|
||||
|
||||
if (localStorage.getItem('prevent_close') === 'true') {
|
||||
e.preventDefault();
|
||||
|
||||
|
||||
return e;
|
||||
}
|
||||
}
|
||||
@@ -52,7 +53,7 @@ window.onhashchange = () => {
|
||||
};
|
||||
|
||||
if (window.self === window.top && location.pathname !== '/view') setTimeout(async () => {
|
||||
Settings.load();
|
||||
loadSettings();
|
||||
|
||||
if (location.pathname === '/games') Games.load();
|
||||
if (location.pathname === '/apps') Apps.load();
|
||||
@@ -61,18 +62,23 @@ if (window.self === window.top && location.pathname !== '/view') setTimeout(asyn
|
||||
}, 500);
|
||||
|
||||
if (location.pathname !== '/view') fetch('/api/changelog')
|
||||
.then(res => res.json())
|
||||
.then(changelog => {
|
||||
document.querySelector('#version').textContent = changelog.version !== 'unknown' ? 'v' + changelog.version : changelog.version;
|
||||
document.querySelector('#version_sha').textContent = changelog.commit.sha.slice(0, 7);
|
||||
document.querySelector('#up_to_date').textContent = changelog.upToDate ? 'yes' : 'no';
|
||||
});
|
||||
.then(res => res.json())
|
||||
.then(changelog => {
|
||||
document.querySelector('#version').textContent = changelog.version !== 'unknown' ? 'v' + changelog.version : changelog.version;
|
||||
document.querySelector('#version_sha').textContent = changelog.commit.sha.slice(0, 7);
|
||||
document.querySelector('#up_to_date').textContent = changelog.upToDate ? 'yes' : 'no';
|
||||
document.querySelector('#mode').textContent = changelog.mode;
|
||||
});
|
||||
|
||||
window.addEventListener('blur', (e) => {
|
||||
|
||||
});
|
||||
|
||||
if (location.pathname === '/') {
|
||||
fetch('/api/games')
|
||||
.then(res => res.json())
|
||||
.then(games => {
|
||||
const gameName = 'Fortnite';
|
||||
const gameName = 'Retro Bowl';
|
||||
const game = games.all.filter(g => g.name === gameName)[0];
|
||||
|
||||
document.querySelector('.featured').addEventListener('click', () => {
|
||||
@@ -87,7 +93,7 @@ if (location.pathname === '/') {
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelector('.featured').src = '/assets/img/wide/fortnite.jpg';
|
||||
document.querySelector('.featured').src = '/assets/img/wide/retrobowl.png';
|
||||
}).catch(e => new PolarisError('Failed to load featured game.'));
|
||||
|
||||
const logHeight = () => {
|
||||
@@ -113,7 +119,7 @@ if (location.pathname === '/') {
|
||||
|
||||
const getAvalibleHeight = () => {
|
||||
var total = 0;
|
||||
|
||||
|
||||
document.querySelectorAll('.container.right>*:not(#changelog)').forEach(el => total += Number((el.currentStyle || window.getComputedStyle(el)).marginTop.replace('px', '')) + Number((el.currentStyle || window.getComputedStyle(el)).marginTop.replace('px', '')) + el.clientHeight);
|
||||
|
||||
return (document.querySelector('.container.right').clientHeight - getVH(2)) - total;
|
||||
|
||||
+317
-311
@@ -5,15 +5,234 @@ import Theme from './themes.js';
|
||||
|
||||
const settingsStorage = storage('settings');
|
||||
|
||||
class Settings {
|
||||
constructor() {
|
||||
if (settingsStorage.get('panic_key')) document.querySelector('#panic_key').value = settingsStorage.get('panic_key');
|
||||
if (settingsStorage.get('panic_url')) document.querySelector('#panic_url').value = settingsStorage.get('panic_url');
|
||||
const loadSidebarInterface = () => {
|
||||
if (settingsStorage.get('panic_key')) document.querySelector('#panic_key').value = settingsStorage.get('panic_key');
|
||||
if (settingsStorage.get('panic_url')) document.querySelector('#panic_url').value = settingsStorage.get('panic_url');
|
||||
|
||||
if (settingsStorage.get('cloak')) {
|
||||
document.querySelector('#cloak_select').value = settingsStorage.get('cloak');
|
||||
if (settingsStorage.get('cloak')) {
|
||||
document.querySelector('#cloak_select').value = settingsStorage.get('cloak');
|
||||
|
||||
if (settingsStorage.get('cloak') == 'custom') {
|
||||
if (settingsStorage.get('cloak') == 'custom') {
|
||||
document.querySelector('#custom_cloak').classList.remove('hidden');
|
||||
|
||||
document.querySelector('#title').addEventListener('input', () => {
|
||||
if (document.querySelector('#title').value) {
|
||||
settingsStorage.set('cloak_title', document.querySelector('#title').value);
|
||||
document.querySelector('title').dataset.value = document.title;
|
||||
document.title = document.querySelector('#title').value;
|
||||
} else document.title = document.querySelector('title').dataset.value;
|
||||
});
|
||||
|
||||
document.querySelector('#domain').addEventListener('input', () => {
|
||||
if (document.querySelector('#domain').value) {
|
||||
settingsStorage.set('cloak_website', document.querySelector('#domain').value);
|
||||
document.querySelector('link[rel=\'shortcut icon\']').href = '/api/favicon?domain=' + document.querySelector('#domain').value;
|
||||
} else document.querySelector('link[rel=\'shortcut icon\']').href = '/favicon.ico';
|
||||
});
|
||||
|
||||
if (settingsStorage.get('cloak_title')) document.querySelector('#title').value = settingsStorage.get('cloak_title');
|
||||
if (settingsStorage.get('cloak_website')) document.querySelector('#domain').value = settingsStorage.get('cloak_website');
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelector('#proxy_select').addEventListener('change', () => settingsStorage.set('proxy', document.querySelector('#proxy_select').value));
|
||||
|
||||
if (settingsStorage.get('proxy')) document.querySelector('#proxy_select').value = settingsStorage.get('proxy');
|
||||
if (navigator.userAgent.includes('Firefox')) document.querySelector('#export_error').innerHTML = 'Your browser does not fully support this feature. Some data may not export.<br><br>';
|
||||
|
||||
document.querySelector('#clear').addEventListener('click', () => {
|
||||
const clearEvents = new EventEmitter();
|
||||
var clearsFinished = 0;
|
||||
|
||||
const clearData = () => {
|
||||
clearsFinished += 1;
|
||||
|
||||
if (clearsFinished === 1) location.reload();
|
||||
}
|
||||
|
||||
clearEvents.on('indexedDB', clearData);
|
||||
|
||||
if (!navigator.userAgent.includes('Firefox')) indexedDB.databases()
|
||||
.then(dbs => {
|
||||
if (dbs.length !== 0) for (let i = 0; i < dbs.length; i++) {
|
||||
const dbInfo = dbs[i];
|
||||
const db = new Dexie(dbInfo.name);
|
||||
|
||||
db.open()
|
||||
.then(() => indexedDBclearer.clearDatabase(db.backendDB())
|
||||
.then((result) => {
|
||||
if (i + 1 === dbs.length) clearEvents.emit('indexedDB');
|
||||
}));
|
||||
} else clearEvents.emit('indexedDB');
|
||||
});
|
||||
else clearEvents.emit('indexedDB');
|
||||
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
document.cookie = '';
|
||||
});
|
||||
|
||||
document.querySelector('#export').addEventListener('click', () => {
|
||||
const CryptoJSScript = document.createElement('script');
|
||||
CryptoJSScript.src = 'https://unpkg.com/crypto-js@latest/crypto-js.js';
|
||||
document.body.appendChild(CryptoJSScript);
|
||||
|
||||
CryptoJSScript.addEventListener('load', () => {
|
||||
const exportEvents = new EventEmitter();
|
||||
var exportsFinished = 0;
|
||||
/**
|
||||
* @type {{ indexedDB: Array<{name: string, data: any}>, cookies: Array<{name: string, data: any}>, localStorage: Array<{name: string, data: any}> }}
|
||||
*/
|
||||
const saveData = {
|
||||
indexedDB: [],
|
||||
cookies: [],
|
||||
localStorage: []
|
||||
};
|
||||
|
||||
const exportData = () => {
|
||||
exportsFinished += 1;
|
||||
|
||||
if (exportsFinished === 3) {
|
||||
const blobURL = URL.createObjectURL(new Blob([CryptoJS.AES.encrypt(JSON.stringify(saveData), 'polaris')]));
|
||||
|
||||
const download = document.createElement('a');
|
||||
download.href = blobURL;
|
||||
download.download = `${new Date().getMonth() + 1}-${new Date().getDate()}-${new Date().getFullYear()}.polarissave`;
|
||||
document.body.appendChild(download);
|
||||
|
||||
download.click();
|
||||
download.remove();
|
||||
URL.revokeObjectURL(blobURL);
|
||||
};
|
||||
};
|
||||
|
||||
exportEvents.on('cookies', exportData);
|
||||
exportEvents.on('indexedDB', exportData);
|
||||
exportEvents.on('localStorage', exportData);
|
||||
|
||||
if (!navigator.userAgent.includes('Firefox')) indexedDB.databases()
|
||||
.then(dbs => {
|
||||
if (dbs.length !== 0) for (let i = 0; i < dbs.length; i++) {
|
||||
const dbInfo = dbs[i];
|
||||
const db = new Dexie(dbInfo.name);
|
||||
|
||||
db.open()
|
||||
.then(() => indexedDBExporter.exportToJsonString(db.backendDB())
|
||||
.then((result) => {
|
||||
try {
|
||||
saveData.indexedDB.push({
|
||||
name: dbInfo.name,
|
||||
data: result
|
||||
});
|
||||
} catch { }
|
||||
|
||||
if (i + 1 === dbs.length) exportEvents.emit('indexedDB');
|
||||
}));
|
||||
} else exportEvents.emit('indexedDB');
|
||||
});
|
||||
else exportEvents.emit('indexedDB');
|
||||
|
||||
if (Object.keys(localStorage).length !== 0) for (let i = 0; i < Object.keys(localStorage).length; i++) {
|
||||
saveData.localStorage.push({
|
||||
name: Object.keys(localStorage)[i],
|
||||
data: localStorage.getItem(Object.keys(localStorage)[i])
|
||||
});
|
||||
|
||||
if (i + 1 === Object.keys(localStorage).length) exportEvents.emit('localStorage');
|
||||
} else exportEvents.emit('localStorage');
|
||||
|
||||
if (Object.keys(cookie.all()).length !== 0) for (let i = 0; i < Object.keys(cookie.all()).length; i++) {
|
||||
saveData.localStorage.push({
|
||||
name: Object.keys(cookie.all())[i],
|
||||
data: cookie.get(Object.keys(cookie.all())[i])
|
||||
});
|
||||
|
||||
if (i + 1 === Object.keys(cookie.all()).length) exportEvents.emit('cookies');
|
||||
} else exportEvents.emit('cookies');
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelector('#import').addEventListener('click', () => {
|
||||
const CryptoJSScript = document.createElement('script');
|
||||
CryptoJSScript.src = 'https://unpkg.com/crypto-js@latest/crypto-js.js';
|
||||
document.body.appendChild(CryptoJSScript);
|
||||
|
||||
CryptoJSScript.addEventListener('load', () => {
|
||||
const uploadInput = document.createElement('input');
|
||||
uploadInput.type = 'file';
|
||||
uploadInput.style.display = 'none';
|
||||
uploadInput.accept = '.polarissave';
|
||||
document.body.appendChild(uploadInput);
|
||||
|
||||
uploadInput.click();
|
||||
|
||||
uploadInput.addEventListener('change', (e) => {
|
||||
uploadInput.remove();
|
||||
|
||||
const file = e.target.files[0];
|
||||
|
||||
if (!file) {
|
||||
uploadInput.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = (e) => {
|
||||
try {
|
||||
const importEvents = new EventEmitter();
|
||||
var importsFinished = 0;
|
||||
/**
|
||||
* @type {{ indexedDB: Array<{name: string, data: any}>, cookies: Array<{name: string, data: any}>, localStorage: Array<{name: string, data: any}> }}
|
||||
*/
|
||||
const saveData = JSON.parse(CryptoJS.AES.decrypt(e.target.result, 'polaris').toString(CryptoJS.enc.Utf8));
|
||||
|
||||
const importData = () => {
|
||||
importsFinished += 1;
|
||||
|
||||
location.reload();
|
||||
};
|
||||
|
||||
importEvents.on('cookies', importData);
|
||||
importEvents.on('indexedDB', importData);
|
||||
importEvents.on('localStorage', importData);
|
||||
|
||||
if (saveData.indexedDB.length !== 0) for (let i = 0; i < saveData.indexedDB.length; i++) {
|
||||
const dbInfo = saveData.indexedDB[i];
|
||||
const db = new Dexie(dbInfo.name);
|
||||
|
||||
db.open()
|
||||
.then(() => indexedDBExporter.importFromJsonString(db.backendDB(), dbInfo.data)
|
||||
.then((result) => {
|
||||
if (i + 1 === dbs.length) importEvents.emit('indexedDB');
|
||||
}));
|
||||
} else importEvents.emit('indexedDB');
|
||||
|
||||
if (saveData.localStorage.length !== 0) for (let i = 0; i < saveData.localStorage.length; i++) {
|
||||
localStorage.setItem(saveData.localStorage[i].name, saveData.localStorage[i].data);
|
||||
|
||||
if (i + 1 === saveData.localStorage.length) importEvents.emit('localStorage');
|
||||
} else importEvents.emit('localStorage');
|
||||
|
||||
if (saveData.cookies.length !== 0) for (let i = 0; i < saveData.cookies.length; i++) {
|
||||
cookie.set(saveData.cookies[i].name, saveData.cookies[i].data);
|
||||
|
||||
if (i + 1 === Object.keys(cookie.all()).length) importEvents.emit('cookies');
|
||||
} else importEvents.emit('cookies');
|
||||
} catch {
|
||||
new PolarisError('Failed to load save file');
|
||||
}
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
fetch('/assets/JSON/cloaks.json').then(res => res.json()).then(cloaks => {
|
||||
document.querySelector('#cloak_select').addEventListener('change', () => {
|
||||
if (document.querySelector('#cloak_select').value == 'custom') {
|
||||
settingsStorage.set('cloak', document.querySelector('#cloak_select').value);
|
||||
document.querySelector('#custom_cloak').classList.remove('hidden');
|
||||
|
||||
document.querySelector('#title').addEventListener('input', () => {
|
||||
@@ -30,323 +249,110 @@ class Settings {
|
||||
document.querySelector('link[rel=\'shortcut icon\']').href = '/api/favicon?domain=' + document.querySelector('#domain').value;
|
||||
} else document.querySelector('link[rel=\'shortcut icon\']').href = '/favicon.ico';
|
||||
});
|
||||
} else if (document.querySelector('#cloak_select').value == 'none') {
|
||||
settingsStorage.set('cloak', document.querySelector('#cloak_select').value);
|
||||
|
||||
if (settingsStorage.get('cloak_title')) {
|
||||
document.querySelector('#title').value = settingsStorage.get('cloak_title');
|
||||
document.querySelector('title').dataset.value = document.title;
|
||||
document.title = settingsStorage.get('cloak_title');
|
||||
}
|
||||
|
||||
if (settingsStorage.get('cloak_website')) {
|
||||
document.querySelector('#domain').value = settingsStorage.get('cloak_website');
|
||||
document.querySelector('link[rel=\'shortcut icon\']').href = '/api/favicon?domain=' + settingsStorage.get('cloak_website');
|
||||
}
|
||||
} else fetch('/assets/JSON/cloaks.json')
|
||||
.then(res => res.json())
|
||||
.then(cloaks => {
|
||||
if (cloaks[settingsStorage.get('cloak')]) {
|
||||
document.title = cloaks[settingsStorage.get('cloak')].title;
|
||||
document.querySelector('link[rel=\'shortcut icon\']').href = cloaks[settingsStorage.get('cloak')].icon;
|
||||
} else if (settingsStorage.get('cloak') !== 'none') new PolarisError(`The cloak ${settingsStorage.get('cloak')} does not exist`);
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelector('#proxy_select').addEventListener('change', () => settingsStorage.set('proxy', document.querySelector('#proxy_select').value));
|
||||
|
||||
if (settingsStorage.get('proxy')) document.querySelector('#proxy_select').value = settingsStorage.get('proxy');
|
||||
if (navigator.userAgent.includes('Firefox')) document.querySelector('#export_error').innerHTML = 'Your browser does not fully support this feature. Some data may not export.<br><br>';
|
||||
|
||||
document.querySelector('#clear').addEventListener('click', () => {
|
||||
const clearEvents = new EventEmitter();
|
||||
var clearsFinished = 0;
|
||||
|
||||
const clearData = () => {
|
||||
clearsFinished += 1;
|
||||
|
||||
if (clearsFinished === 1) location.reload();
|
||||
}
|
||||
|
||||
clearEvents.on('indexedDB', clearData);
|
||||
|
||||
if (!navigator.userAgent.includes('Firefox')) indexedDB.databases()
|
||||
.then(dbs => {
|
||||
if (dbs.length !== 0) for (let i = 0; i < dbs.length; i++) {
|
||||
const dbInfo = dbs[i];
|
||||
const db = new Dexie(dbInfo.name);
|
||||
|
||||
db.open()
|
||||
.then(() => indexedDBclearer.clearDatabase(db.backendDB())
|
||||
.then((result) => {
|
||||
if (i + 1 === dbs.length) clearEvents.emit('indexedDB');
|
||||
}));
|
||||
} else clearEvents.emit('indexedDB');
|
||||
});
|
||||
else clearEvents.emit('indexedDB');
|
||||
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
document.cookie = '';
|
||||
});
|
||||
|
||||
document.querySelector('#export').addEventListener('click', () => {
|
||||
const CryptoJSScript = document.createElement('script');
|
||||
CryptoJSScript.src = 'https://unpkg.com/crypto-js@latest/crypto-js.js';
|
||||
document.body.appendChild(CryptoJSScript);
|
||||
|
||||
CryptoJSScript.addEventListener('load', () => {
|
||||
const exportEvents = new EventEmitter();
|
||||
var exportsFinished = 0;
|
||||
/**
|
||||
* @type {{ indexedDB: Array<{name: string, data: any}>, cookies: Array<{name: string, data: any}>, localStorage: Array<{name: string, data: any}> }}
|
||||
*/
|
||||
const saveData = {
|
||||
indexedDB: [],
|
||||
cookies: [],
|
||||
localStorage: []
|
||||
};
|
||||
|
||||
const exportData = () => {
|
||||
exportsFinished += 1;
|
||||
|
||||
if (exportsFinished === 3) {
|
||||
const blobURL = URL.createObjectURL(new Blob([CryptoJS.AES.encrypt(JSON.stringify(saveData), 'polaris')]));
|
||||
|
||||
const download = document.createElement('a');
|
||||
download.href = blobURL;
|
||||
download.download = `${new Date().getMonth() + 1}-${new Date().getDate()}-${new Date().getFullYear()}.polarissave`;
|
||||
document.body.appendChild(download);
|
||||
|
||||
download.click();
|
||||
download.remove();
|
||||
URL.revokeObjectURL(blobURL);
|
||||
};
|
||||
};
|
||||
|
||||
exportEvents.on('cookies', exportData);
|
||||
exportEvents.on('indexedDB', exportData);
|
||||
exportEvents.on('localStorage', exportData);
|
||||
|
||||
if (!navigator.userAgent.includes('Firefox')) indexedDB.databases()
|
||||
.then(dbs => {
|
||||
if (dbs.length !== 0) for (let i = 0; i < dbs.length; i++) {
|
||||
const dbInfo = dbs[i];
|
||||
const db = new Dexie(dbInfo.name);
|
||||
|
||||
db.open()
|
||||
.then(() => indexedDBExporter.exportToJsonString(db.backendDB())
|
||||
.then((result) => {
|
||||
try {
|
||||
saveData.indexedDB.push({
|
||||
name: dbInfo.name,
|
||||
data: result
|
||||
});
|
||||
} catch { }
|
||||
|
||||
if (i + 1 === dbs.length) exportEvents.emit('indexedDB');
|
||||
}));
|
||||
} else exportEvents.emit('indexedDB');
|
||||
});
|
||||
else exportEvents.emit('indexedDB');
|
||||
|
||||
if (Object.keys(localStorage).length !== 0) for (let i = 0; i < Object.keys(localStorage).length; i++) {
|
||||
saveData.localStorage.push({
|
||||
name: Object.keys(localStorage)[i],
|
||||
data: localStorage.getItem(Object.keys(localStorage)[i])
|
||||
});
|
||||
|
||||
if (i + 1 === Object.keys(localStorage).length) exportEvents.emit('localStorage');
|
||||
} else exportEvents.emit('localStorage');
|
||||
|
||||
if (Object.keys(cookie.all()).length !== 0) for (let i = 0; i < Object.keys(cookie.all()).length; i++) {
|
||||
saveData.localStorage.push({
|
||||
name: Object.keys(cookie.all())[i],
|
||||
data: cookie.get(Object.keys(cookie.all())[i])
|
||||
});
|
||||
|
||||
if (i + 1 === Object.keys(cookie.all()).length) exportEvents.emit('cookies');
|
||||
} else exportEvents.emit('cookies');
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelector('#import').addEventListener('click', () => {
|
||||
const CryptoJSScript = document.createElement('script');
|
||||
CryptoJSScript.src = 'https://unpkg.com/crypto-js@latest/crypto-js.js';
|
||||
document.body.appendChild(CryptoJSScript);
|
||||
|
||||
CryptoJSScript.addEventListener('load', () => {
|
||||
const uploadInput = document.createElement('input');
|
||||
uploadInput.type = 'file';
|
||||
uploadInput.style.display = 'none';
|
||||
uploadInput.accept = '.polarissave';
|
||||
document.body.appendChild(uploadInput);
|
||||
|
||||
uploadInput.click();
|
||||
|
||||
uploadInput.addEventListener('change', (e) => {
|
||||
uploadInput.remove();
|
||||
|
||||
const file = e.target.files[0];
|
||||
|
||||
if (!file) {
|
||||
uploadInput.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = (e) => {
|
||||
try {
|
||||
const importEvents = new EventEmitter();
|
||||
var importsFinished = 0;
|
||||
/**
|
||||
* @type {{ indexedDB: Array<{name: string, data: any}>, cookies: Array<{name: string, data: any}>, localStorage: Array<{name: string, data: any}> }}
|
||||
*/
|
||||
const saveData = JSON.parse(CryptoJS.AES.decrypt(e.target.result, 'polaris').toString(CryptoJS.enc.Utf8));
|
||||
|
||||
const importData = () => {
|
||||
importsFinished += 1;
|
||||
|
||||
location.reload();
|
||||
};
|
||||
|
||||
importEvents.on('cookies', importData);
|
||||
importEvents.on('indexedDB', importData);
|
||||
importEvents.on('localStorage', importData);
|
||||
|
||||
if (saveData.indexedDB.length !== 0) for (let i = 0; i < saveData.indexedDB.length; i++) {
|
||||
const dbInfo = saveData.indexedDB[i];
|
||||
const db = new Dexie(dbInfo.name);
|
||||
|
||||
db.open()
|
||||
.then(() => indexedDBExporter.importFromJsonString(db.backendDB(), dbInfo.data)
|
||||
.then((result) => {
|
||||
if (i + 1 === dbs.length) importEvents.emit('indexedDB');
|
||||
}));
|
||||
} else importEvents.emit('indexedDB');
|
||||
|
||||
if (saveData.localStorage.length !== 0) for (let i = 0; i < saveData.localStorage.length; i++) {
|
||||
localStorage.setItem(saveData.localStorage[i].name, saveData.localStorage[i].data);
|
||||
|
||||
if (i + 1 === saveData.localStorage.length) importEvents.emit('localStorage');
|
||||
} else importEvents.emit('localStorage');
|
||||
|
||||
if (saveData.cookies.length !== 0) for (let i = 0; i < saveData.cookies.length; i++) {
|
||||
cookie.set(saveData.cookies[i].name, saveData.cookies[i].data);
|
||||
|
||||
if (i + 1 === Object.keys(cookie.all()).length) importEvents.emit('cookies');
|
||||
} else importEvents.emit('cookies');
|
||||
} catch {
|
||||
new PolarisError('Failed to load save file');
|
||||
}
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
fetch('/assets/JSON/cloaks.json').then(res => res.json()).then(cloaks => {
|
||||
document.querySelector('#cloak_select').addEventListener('change', () => {
|
||||
if (document.querySelector('#cloak_select').value == 'custom') {
|
||||
settingsStorage.set('cloak', document.querySelector('#cloak_select').value);
|
||||
document.querySelector('#custom_cloak').classList.remove('hidden');
|
||||
|
||||
document.querySelector('#title').addEventListener('input', () => {
|
||||
if (document.querySelector('#title').value) {
|
||||
settingsStorage.set('cloak_title', document.querySelector('#title').value);
|
||||
document.querySelector('title').dataset.value = document.title;
|
||||
document.title = document.querySelector('#title').value;
|
||||
} else document.title = document.querySelector('title').dataset.value;
|
||||
});
|
||||
|
||||
document.querySelector('#domain').addEventListener('input', () => {
|
||||
if (document.querySelector('#domain').value) {
|
||||
settingsStorage.set('cloak_website', document.querySelector('#domain').value);
|
||||
document.querySelector('link[rel=\'shortcut icon\']').href = '/api/favicon?domain=' + document.querySelector('#domain').value;
|
||||
} else document.querySelector('link[rel=\'shortcut icon\']').href = '/favicon.ico';
|
||||
});
|
||||
} else if (document.querySelector('#cloak_select').value == 'none') {
|
||||
settingsStorage.set('cloak', document.querySelector('#cloak_select').value);
|
||||
|
||||
document.title = document.querySelector('title').dataset.value;
|
||||
document.querySelector('link[rel=\'shortcut icon\']').href = '/favicon.ico';
|
||||
document.querySelector('#custom_cloak').classList.add('hidden');
|
||||
} else {
|
||||
if (cloaks[document.querySelector('#cloak_select').value]) {
|
||||
document.querySelector('title').dataset.value = document.title;
|
||||
document.title = cloaks[document.querySelector('#cloak_select').value].title;
|
||||
document.querySelector('link[rel=\'shortcut icon\']').href = cloaks[document.querySelector('#cloak_select').value].icon;
|
||||
settingsStorage.set('cloak', document.querySelector('#cloak_select').value);
|
||||
} else new PolarisError(`The cloak ${document.querySelector('#cloak_select').value} does not exist`);
|
||||
|
||||
document.querySelector('#custom_cloak').classList.add('hidden');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelector('#reset_panic').addEventListener('click', (e) => {
|
||||
settingsStorage.set('panic_key', '');
|
||||
document.querySelector('#panic_key').value = 'No Key Selected';
|
||||
});
|
||||
|
||||
document.querySelector('#panic_url').addEventListener('input', (e) => settingsStorage.set('panic_url', document.querySelector('#panic_url').value));
|
||||
|
||||
window.onkeydown = (e) => {
|
||||
if (document.querySelector('#panic_key') == document.activeElement) {
|
||||
document.querySelector('#panic_key').value = e.key;
|
||||
settingsStorage.set('panic_key', document.querySelector('#panic_key').value);
|
||||
document.title = document.querySelector('title').dataset.value;
|
||||
document.querySelector('link[rel=\'shortcut icon\']').href = '/favicon.ico';
|
||||
document.querySelector('#custom_cloak').classList.add('hidden');
|
||||
} else {
|
||||
if (e.key === settingsStorage.get('panic_key')) {
|
||||
if (settingsStorage.get('panic_url')) window.location.href = settingsStorage.get('panic_url');
|
||||
else new PolarisError('A panic key was used but no url was found.');
|
||||
}
|
||||
if (cloaks[document.querySelector('#cloak_select').value]) {
|
||||
document.querySelector('title').dataset.value = document.title;
|
||||
document.title = cloaks[document.querySelector('#cloak_select').value].title;
|
||||
document.querySelector('link[rel=\'shortcut icon\']').href = cloaks[document.querySelector('#cloak_select').value].icon;
|
||||
settingsStorage.set('cloak', document.querySelector('#cloak_select').value);
|
||||
} else new PolarisError(`The cloak ${document.querySelector('#cloak_select').value} does not exist`);
|
||||
|
||||
document.querySelector('#custom_cloak').classList.add('hidden');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelector('#reset_panic').addEventListener('click', (e) => {
|
||||
settingsStorage.set('panic_key', '');
|
||||
document.querySelector('#panic_key').value = 'No Key Selected';
|
||||
});
|
||||
|
||||
document.querySelector('#panic_url').addEventListener('input', (e) => settingsStorage.set('panic_url', document.querySelector('#panic_url').value));
|
||||
|
||||
window.onkeydown = (e) => {
|
||||
if (document.querySelector('#panic_key') == document.activeElement) {
|
||||
document.querySelector('#panic_key').value = e.key;
|
||||
settingsStorage.set('panic_key', document.querySelector('#panic_key').value);
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelector('#themes').querySelectorAll('button').forEach(el => el.onclick = () => Theme.set(el.innerText.toLocaleLowerCase()));
|
||||
document.querySelector('#themes').querySelectorAll('button').forEach(el => el.onclick = () => Theme.set(el.innerText.toLocaleLowerCase()));
|
||||
|
||||
if (window.location.hash.slice(1)) {
|
||||
document.querySelector('.sidebar').style.transition = 'all 0s ease';
|
||||
document.querySelector('.sidebar').classList.add('active');
|
||||
if (window.location.hash.slice(1)) {
|
||||
document.querySelector('.sidebar').style.transition = 'all 0s ease';
|
||||
document.querySelector('.sidebar').classList.add('active');
|
||||
|
||||
setInterval(() => document.querySelector('.sidebar').removeAttribute('style'), 1000);
|
||||
}
|
||||
setInterval(() => document.querySelector('.sidebar').removeAttribute('style'), 1000);
|
||||
}
|
||||
|
||||
if (sessionStorage.getItem('settings-open') === 'true') {
|
||||
document.querySelector('.sidebar').style.transition = 'all 0s ease';
|
||||
document.querySelector('.sidebar').classList.add('active');
|
||||
if (sessionStorage.getItem('settings-open') === 'true') {
|
||||
document.querySelector('.sidebar').style.transition = 'all 0s ease';
|
||||
document.querySelector('.sidebar').classList.add('active');
|
||||
|
||||
setInterval(() => document.querySelector('.sidebar').removeAttribute('style'), 1000);
|
||||
setInterval(() => document.querySelector('.sidebar').removeAttribute('style'), 1000);
|
||||
|
||||
window.history.pushState({}, '', '#settings');
|
||||
}
|
||||
window.history.pushState({}, '', '#settings');
|
||||
}
|
||||
|
||||
document.querySelectorAll('[data-attr=\'sidebar_trigger\']').forEach(el => {
|
||||
el.addEventListener('click', (e) => {
|
||||
if (document.querySelector('.sidebar').classList.contains('active')) {
|
||||
document.querySelector('.sidebar').classList.remove('active');
|
||||
document.querySelectorAll('[data-attr=\'sidebar_trigger\']').forEach(el => {
|
||||
el.addEventListener('click', (e) => {
|
||||
if (document.querySelector('.sidebar').classList.contains('active')) {
|
||||
document.querySelector('.sidebar').classList.remove('active');
|
||||
|
||||
setTimeout(() => window.history.pushState({}, '', location.href.split('#')[0]), 50);
|
||||
setTimeout(() => window.history.pushState({}, '', location.href.split('#')[0]), 50);
|
||||
|
||||
sessionStorage.setItem('settings-open', false);
|
||||
} else {
|
||||
document.querySelector('.sidebar').classList.add('active');
|
||||
sessionStorage.setItem('settings-open', true);
|
||||
}
|
||||
sessionStorage.setItem('settings-open', false);
|
||||
} else {
|
||||
document.querySelector('.sidebar').classList.add('active');
|
||||
sessionStorage.setItem('settings-open', true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (isScrollable(document.querySelector('.sidebar'))) document.querySelector('.scroll').classList.add('active');
|
||||
|
||||
document.querySelector('.scroll').addEventListener('click', () => document.querySelector('.sidebar').scrollTop = document.querySelector('.sidebar').scrollHeight);
|
||||
|
||||
document.querySelector('.sidebar').addEventListener('scroll', () => {
|
||||
if (document.querySelector('.sidebar').scrollTop + document.querySelector('.sidebar').clientHeight >= document.querySelector('.sidebar').scrollHeight - 1) document.querySelector('.scroll').classList.remove('active');
|
||||
else document.querySelector('.scroll').classList.add('active');
|
||||
});
|
||||
|
||||
loadSettings();
|
||||
};
|
||||
|
||||
const loadSettings = () => {
|
||||
if (settingsStorage.get('cloak')) {
|
||||
if (settingsStorage.get('cloak') == 'custom') {
|
||||
if (settingsStorage.get('cloak_title')) {
|
||||
document.querySelector('title').dataset.value = document.title;
|
||||
document.title = settingsStorage.get('cloak_title');
|
||||
}
|
||||
|
||||
if (settingsStorage.get('cloak_website')) document.querySelector('link[rel=\'shortcut icon\']').href = '/api/favicon?domain=' + settingsStorage.get('cloak_website');
|
||||
} else fetch('/assets/JSON/cloaks.json')
|
||||
.then(res => res.json())
|
||||
.then(cloaks => {
|
||||
if (cloaks[settingsStorage.get('cloak')]) {
|
||||
document.title = cloaks[settingsStorage.get('cloak')].title;
|
||||
document.querySelector('link[rel=\'shortcut icon\']').href = cloaks[settingsStorage.get('cloak')].icon;
|
||||
} else if (settingsStorage.get('cloak') !== 'none') new PolarisError(`The cloak ${settingsStorage.get('cloak')} does not exist`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (isScrollable(document.querySelector('.sidebar'))) document.querySelector('.scroll').classList.add('active');
|
||||
window.onkeydown = (e) => {
|
||||
if (e.key === settingsStorage.get('panic_key')) {
|
||||
if (settingsStorage.get('panic_url')) window.location.href = settingsStorage.get('panic_url');
|
||||
else new PolarisError('A panic key was used but no url was found.');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
document.querySelector('.scroll').addEventListener('click', () => document.querySelector('.sidebar').scrollTop = document.querySelector('.sidebar').scrollHeight);
|
||||
|
||||
document.querySelector('.sidebar').addEventListener('scroll', () => {
|
||||
if (document.querySelector('.sidebar').scrollTop + document.querySelector('.sidebar').clientHeight >= document.querySelector('.sidebar').scrollHeight - 1) document.querySelector('.scroll').classList.remove('active');
|
||||
else document.querySelector('.scroll').classList.add('active');
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const load = () => new Settings();
|
||||
|
||||
export default { load, Settings };
|
||||
export default { loadSettings, loadSidebarInterface };
|
||||
export { loadSettings, loadSidebarInterface };
|
||||
@@ -8,13 +8,16 @@ class CrossTabCommunication extends EventEmitter {
|
||||
this.openConnections = {};
|
||||
this.id = this.registrar.register({
|
||||
location: location.href,
|
||||
...data || {}
|
||||
...data
|
||||
});
|
||||
|
||||
//Worker stuff
|
||||
this.worker.send('id', this.id);
|
||||
// Worker stuff
|
||||
this.worker.worker.addEventListener('message', async ({ data: message }) => {
|
||||
if (this.worker.handlers[message.action]) this.worker.respond(message.transactionID, await this.worker.handlers[message.action](message.data) || {});
|
||||
if (this.worker.handlers[message.action]) this.worker.respond(message.transactionID, await this.worker.handlers[message.action](message.data));
|
||||
|
||||
if (message.action === 'ready') await this.worker.response(this.worker.send('init', {
|
||||
id: this.id
|
||||
}));
|
||||
});
|
||||
|
||||
this.worker.handleRequest('localstorage', (data) => localStorage[data.action](...data.params));
|
||||
@@ -22,7 +25,7 @@ class CrossTabCommunication extends EventEmitter {
|
||||
localStorage.setItem('ctc_' + this.id, 'open');
|
||||
|
||||
window.addEventListener('beforeunload', (e) => {
|
||||
delete this.registrar.registrationData[id];
|
||||
delete this.registrar.registrationData[this.id];
|
||||
|
||||
this.registrar.registrationData = {
|
||||
...this.registrar.registrationData,
|
||||
@@ -94,7 +97,7 @@ class CrossTabCommunication extends EventEmitter {
|
||||
postMessage({
|
||||
transactionID,
|
||||
action,
|
||||
data: data || {}
|
||||
data: data
|
||||
});
|
||||
|
||||
return transactionID;
|
||||
@@ -154,7 +157,7 @@ class CrossTabCommunication extends EventEmitter {
|
||||
* @param {'public' | 'private'} type The type of channel
|
||||
* @returns {boolean}
|
||||
*/
|
||||
channelExists = (remoteID, type) => Boolean(localStorage.getItem(type === 'private' ? 'ctc_connection' + this.id + '>' + remoteID : 'ctc_' + remoteID))
|
||||
channelExists = (remoteID, type) => Boolean(localStorage.getItem(type === 'private' ? 'ctc_connection' + this.id + '>' + remoteID : 'ctc_' + remoteID));
|
||||
|
||||
/**
|
||||
* Listen for messages on a channel
|
||||
@@ -305,22 +308,26 @@ class Worker extends EventEmitter {
|
||||
this.handlers = {};
|
||||
|
||||
this.on('message', async (message) => {
|
||||
if (this.handlers[message.action]) this.respond(message.transactionID, await this.handlers[message.action](message.data) || {});
|
||||
if (this.handlers[message.action]) this.respond(message.transactionID, await this.handlers[message.action](message.data));
|
||||
});
|
||||
|
||||
/*const listener = this.listen(this.id, 'public');
|
||||
this.handleRequest('init', () => new Promise((resolve, reject) => {
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.id = message.id;
|
||||
|
||||
listener.on('message', (message) => {
|
||||
if (message.startsWith('ctc:connection:')) {
|
||||
const connection = this.interfaceConnection(message.replace('ctc:connection:', ''));
|
||||
console.log(this.id);
|
||||
|
||||
this.emit('open', connection);
|
||||
}
|
||||
});*/
|
||||
this.listen(this.id, 'public')
|
||||
.then((listener) => listener.on('message', (message) => {
|
||||
if (message.startsWith('ctc:connection:')) {
|
||||
const connection = this.interfaceConnection(message.replace('ctc:connection:', ''));
|
||||
|
||||
this.handleRequest('destroy', (message) => {
|
||||
|
||||
});
|
||||
this.emit('open', connection);
|
||||
}
|
||||
}));
|
||||
}));
|
||||
|
||||
this.send('ready');
|
||||
}
|
||||
@@ -379,6 +386,51 @@ class Worker extends EventEmitter {
|
||||
}))
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a channel exists
|
||||
* @param {string} remoteID The remote client id
|
||||
* @param {'public' | 'private'} type The type of channel
|
||||
* @returns {Promise.<boolean>}
|
||||
*/
|
||||
channelExists = async (remoteID, type) => Boolean(await this.localStorage.getItem(type === 'private' ? 'ctc_connection' + this.id + '>' + remoteID : 'ctc_' + remoteID));
|
||||
|
||||
/**
|
||||
* Listen for messages on a channel
|
||||
* @param {string} remoteID The remote client id
|
||||
* @param {'public' | 'private'} type The type of channel
|
||||
* @returns {{ on: (event: 'message' | 'disconnect', callback: (...any) => any) => {}, once: (event: 'message' | 'disconnect', callback: (...any) => any) => {}, addEventListener: (event: 'message' | 'disconnect', callback: (...any) => any) => {}, disconnect: () => {} }}
|
||||
*/
|
||||
listen = async (remoteID, type) => {
|
||||
console.log(await this.localStorage.getItem(type === 'private' ? 'ctc_connection' + this.id + '>' + remoteID : 'ctc_' + remoteID));
|
||||
|
||||
if (await this.channelExists(remoteID, type)) {
|
||||
const channel = type === 'private' ? 'ctc_connection' + this.id + '>' + remoteID : 'ctc_' + remoteID;
|
||||
var prev = await this.localStorage.getItem(channel);
|
||||
const events = new EventEmitter();
|
||||
|
||||
const listener = setInterval(async () => {
|
||||
if (await this.localStorage.getItem(channel)) {
|
||||
if (prev !== await this.localStorage.getItem(channel)) {
|
||||
prev = await this.localStorage.getItem(channel);
|
||||
|
||||
events.emit('message', await this.localStorage.getItem(channel));
|
||||
}
|
||||
} else {
|
||||
clearInterval(listener);
|
||||
events.emit('disconnect');
|
||||
}
|
||||
}, 1);
|
||||
|
||||
return {
|
||||
...events,
|
||||
disconnect: () => {
|
||||
clearInterval(listener);
|
||||
events.emit('disconnect');
|
||||
}
|
||||
};
|
||||
} else throw new Error('Invalid channel');
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to the parent process
|
||||
* @param {string} action The action
|
||||
@@ -391,7 +443,7 @@ class Worker extends EventEmitter {
|
||||
postMessage({
|
||||
transactionID,
|
||||
action,
|
||||
data: data || {}
|
||||
data: data
|
||||
});
|
||||
|
||||
return transactionID;
|
||||
@@ -403,9 +455,9 @@ class Worker extends EventEmitter {
|
||||
* @returns {any}
|
||||
*/
|
||||
response = (transactionID) => new Promise((resolve, reject) => {
|
||||
const listener = this.on('message', (data) => {
|
||||
if (data.transactionID === transactionID && data.action === 'response') {
|
||||
resolve(data.data);
|
||||
const listener = this.on('message', (message) => {
|
||||
if (message.transactionID === transactionID && message.action === 'response') {
|
||||
resolve(message.data);
|
||||
this.off('message', listener);
|
||||
}
|
||||
});
|
||||
@@ -427,7 +479,7 @@ class Worker extends EventEmitter {
|
||||
* @param {string} action The request type
|
||||
* @param {(data: any) => {}} handler The handler
|
||||
*/
|
||||
handleRequest = (action, handler) => this.worker.handlers[action] = handler;
|
||||
handleRequest = (action, handler) => this.handlers[action] = handler;
|
||||
}
|
||||
|
||||
export default CrossTabCommunication;
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { loadProxyWorker, encoder, storage } from './utils.js';
|
||||
import { loadSettings } from './settings.js';
|
||||
|
||||
loadSettings();
|
||||
|
||||
const params = new URLSearchParams(location.search);
|
||||
const settingsStorage = storage('settings');
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
Commit: <span id="changelog_version_sha">unknown</span>
|
||||
<br>
|
||||
Up to Date: <span id="changelog_up_to_date">no</span>
|
||||
<br>
|
||||
Server Mode: <span id="changelog_mode">unknown</span>
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ window['nitroAds'].createAd('outstreamplayer1', {
|
||||
|
||||
<h1 style="font-size: 4vh;" class="gamesectionheader">All Games</h1>
|
||||
|
||||
<input type="text" id="searchInput" placeholder="Search Games...">
|
||||
<input type="text" id="searchInput" placeholder="Search Games">
|
||||
<br>
|
||||
|
||||
<!--el:ad_horizontal-->
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
<div class="container">
|
||||
<h1 class="nomargin">Featured Game</h1>
|
||||
|
||||
<img class="featured" data-link="true" />
|
||||
<img class="featured" />
|
||||
</div>
|
||||
|
||||
<div class="container right">
|
||||
|
||||
@@ -78,6 +78,8 @@
|
||||
Commit: <span id="version_sha">unknown</span>
|
||||
<br>
|
||||
Up to Date: <span id="up_to_date">no</span>
|
||||
<br>
|
||||
Server Mode: <span id="mode">unknown</span>
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
Reference in New Issue
Block a user