Merge branch 'v3' of https://github.com/wearrrrr/AlusUnblocker into v3
This commit is contained in:
commit
94f210f7f7
41 changed files with 14544 additions and 12454 deletions
2
.prettierignore
Normal file
2
.prettierignore
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
dist
|
||||
node_modules
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
import { defineConfig } from "astro/config";
|
||||
|
||||
import node from "@astrojs/node";
|
||||
|
||||
|
|
@ -8,5 +8,5 @@ export default defineConfig({
|
|||
output: "hybrid",
|
||||
adapter: node({
|
||||
mode: "middleware",
|
||||
})
|
||||
});
|
||||
}),
|
||||
});
|
||||
|
|
|
|||
108
index.js
108
index.js
|
|
@ -1,56 +1,96 @@
|
|||
import { createBareServer } from "@tomphttp/bare-server-node"
|
||||
import { uvPath } from "@nebula-services/ultraviolet"
|
||||
import http from 'node:http';
|
||||
import path from 'node:path';
|
||||
import express from 'express';
|
||||
import { handler as ssrHandler } from './dist/server/entry.mjs';
|
||||
import dotenv from 'dotenv';
|
||||
import compression from "compression"
|
||||
import chalk from "chalk"
|
||||
import { uvPath } from "@nebula-services/ultraviolet";
|
||||
import { createBareServer } from "@tomphttp/bare-server-node";
|
||||
import express from "express";
|
||||
import { createServer } from "http";
|
||||
import path from "node:path";
|
||||
import createRammerhead from "rammerhead/src/server/index.js";
|
||||
import compression from "compression";
|
||||
import { build } from "astro";
|
||||
import chalk from "chalk";
|
||||
import { existsSync } from "fs";
|
||||
import dotenv from "dotenv";
|
||||
dotenv.config();
|
||||
|
||||
if (!existsSync("./dist")) build();
|
||||
|
||||
const PORT = process.env.PORT || 3000;
|
||||
|
||||
const server = http.createServer();
|
||||
const app = express(server);
|
||||
const bareServer = createBareServer("/bare/");
|
||||
app.use(compression());
|
||||
app.use(express.static(path.join(process.cwd(), "static")));
|
||||
app.use(express.static(path.join(process.cwd(), "build")));
|
||||
app.use("/uv/", express.static(uvPath));
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({
|
||||
extended: true
|
||||
})
|
||||
);
|
||||
app.use("/", express.static('dist/client/'));
|
||||
app.use(ssrHandler);
|
||||
const bare = createBareServer("/bare/");
|
||||
|
||||
app.get('*', function(req, res){
|
||||
res.status(200).sendFile("404.html", {root: path.resolve("dist/client")});
|
||||
});
|
||||
const rh = createRammerhead();
|
||||
|
||||
const rammerheadScopes = [
|
||||
"/rammerhead.js",
|
||||
"/hammerhead.js",
|
||||
"/transport-worker.js",
|
||||
"/task.js",
|
||||
"/iframe-task.js",
|
||||
"/worker-hammerhead.js",
|
||||
"/messaging",
|
||||
"/sessionexists",
|
||||
"/deletesession",
|
||||
"/newsession",
|
||||
"/editsession",
|
||||
"/needpassword",
|
||||
"/syncLocalStorage",
|
||||
"/api/shuffleDict",
|
||||
"/mainport",
|
||||
];
|
||||
|
||||
const rammerheadSession = /^\/[a-z0-9]{32}/;
|
||||
|
||||
function shouldRouteRh(req) {
|
||||
const url = new URL(req.url, "http://0.0.0.0");
|
||||
return rammerheadScopes.includes(url.pathname) || rammerheadSession.test(url.pathname);
|
||||
}
|
||||
|
||||
function routeRhRequest(req, res) {
|
||||
rh.emit("request", req, res);
|
||||
}
|
||||
|
||||
function routeRhUpgrade(req, socket, head) {
|
||||
rh.emit("upgrade", req, socket, head);
|
||||
}
|
||||
|
||||
let server = createServer();
|
||||
server.on("request", (req, res) => {
|
||||
if (bareServer.shouldRoute(req)) {
|
||||
bareServer.routeRequest(req, res);
|
||||
if (bare.shouldRoute(req)) {
|
||||
bare.routeRequest(req, res);
|
||||
} else if (shouldRouteRh(req)) {
|
||||
routeRhRequest(req, res);
|
||||
} else {
|
||||
app(req, res);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
server.on("upgrade", (req, socket, head) => {
|
||||
if (bareServer.shouldRoute(req)) {
|
||||
bareServer.routeUpgrade(req, socket, head);
|
||||
if (bare.shouldRoute(req)) {
|
||||
bare.routeUpgrade(req, socket, head);
|
||||
} else if (shouldRouteRh(req)) {
|
||||
routeRhUpgrade(req, socket, head);
|
||||
} else {
|
||||
socket.end();
|
||||
}
|
||||
});
|
||||
|
||||
console.log(chalk.gray("Starting Alu..."))
|
||||
const app = express();
|
||||
app.use(compression());
|
||||
app.use(express.static(path.join(process.cwd(), "static")));
|
||||
app.use(express.static(path.join(process.cwd(), "build")));
|
||||
app.use("/uv/", express.static(uvPath));
|
||||
app.use(express.json());
|
||||
app.use(
|
||||
express.urlencoded({
|
||||
extended: true,
|
||||
})
|
||||
);
|
||||
app.use("/", express.static("dist/client/"));
|
||||
|
||||
console.log(chalk.gray("Starting Alu..."));
|
||||
server.on("listening", () => {
|
||||
console.log(chalk.green(`Server running at http://localhost:${PORT}/.`));
|
||||
});
|
||||
|
||||
server.listen({
|
||||
port: PORT
|
||||
});
|
||||
port: PORT,
|
||||
});
|
||||
|
|
|
|||
58
index.js.bak
Normal file
58
index.js.bak
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import { createBareServer } from "@tomphttp/bare-server-node";
|
||||
import { uvPath } from "@nebula-services/ultraviolet";
|
||||
import http from "node:http";
|
||||
import path from "node:path";
|
||||
import express from "express";
|
||||
import { handler as ssrHandler } from "./dist/server/entry.mjs";
|
||||
import dotenv from "dotenv";
|
||||
import compression from "compression";
|
||||
import createRammerhead from "rammerhead/src/server/index.js";
|
||||
import chalk from "chalk";
|
||||
dotenv.config();
|
||||
|
||||
const PORT = process.env.PORT || 3000;
|
||||
|
||||
const server = http.createServer();
|
||||
const app = express(server);
|
||||
const bareServer = createBareServer("/bare/");
|
||||
app.use(compression());
|
||||
app.use(express.static(path.join(process.cwd(), "static")));
|
||||
app.use(express.static(path.join(process.cwd(), "build")));
|
||||
app.use("/uv/", express.static(uvPath));
|
||||
app.use(express.json());
|
||||
app.use(
|
||||
express.urlencoded({
|
||||
extended: true,
|
||||
})
|
||||
);
|
||||
app.use("/", express.static("dist/client/"));
|
||||
app.use(ssrHandler);
|
||||
|
||||
app.get("*", function (req, res) {
|
||||
res.status(200).sendFile("404.html", { root: path.resolve("dist/client") });
|
||||
});
|
||||
|
||||
server.on('request', (req, res) => {
|
||||
if (bareServer.shouldRoute(req)) {
|
||||
bareServer.routeRequest(req, res);
|
||||
} else {
|
||||
app(req, res);
|
||||
}
|
||||
});
|
||||
|
||||
server.on('upgrade', (req, socket, head) => {
|
||||
if (bareServer.shouldRoute(req)) {
|
||||
bareServer.routeUpgrade(req, socket, head);
|
||||
} else {
|
||||
socket.end();
|
||||
}
|
||||
});
|
||||
|
||||
console.log(chalk.gray("Starting Alu..."));
|
||||
server.on("listening", () => {
|
||||
console.log(chalk.green(`Server running at http://localhost:${PORT}/.`));
|
||||
});
|
||||
|
||||
server.listen({
|
||||
port: PORT,
|
||||
});
|
||||
22889
package-lock.json
generated
22889
package-lock.json
generated
File diff suppressed because it is too large
Load diff
59
package.json
59
package.json
|
|
@ -1,27 +1,36 @@
|
|||
{
|
||||
"name": "alus-unblocker",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"start": "node .",
|
||||
"build": "astro build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.4.0",
|
||||
"@astrojs/node": "^7.0.4",
|
||||
"@nebula-services/ultraviolet": "^1.0.1-1.patch.5",
|
||||
"@tomphttp/bare-server-node": "^2.0.1",
|
||||
"astro": "^4.1.1",
|
||||
"astro-i18n": "^2.2.4",
|
||||
"astro-i18next": "^1.0.0-beta.21",
|
||||
"chalk": "^5.3.0",
|
||||
"compression": "^1.7.4",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"i": "^0.3.7",
|
||||
"i18next": "^23.7.18",
|
||||
"i18next-browser-languagedetector": "^7.2.0",
|
||||
"npm": "^10.2.5",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
"name": "alus-unblocker",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"start": "node .",
|
||||
"build": "astro build",
|
||||
"lint": "prettier --write .",
|
||||
"lint:check": "prettier --check ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.4.0",
|
||||
"@astrojs/node": "^7.0.4",
|
||||
"@nebula-services/ultraviolet": "^1.0.1-1.patch.5",
|
||||
"@tomphttp/bare-server-node": "^2.0.1",
|
||||
"astro": "^4.3.3",
|
||||
"astro-i18n": "^2.2.4",
|
||||
"astro-i18next": "^1.0.0-beta.21",
|
||||
"chalk": "^5.3.0",
|
||||
"compression": "^1.7.4",
|
||||
"dotenv": "^16.3.1",
|
||||
"dotenv-flow": "^4.1.0",
|
||||
"express": "^4.18.2",
|
||||
"i": "^0.3.7",
|
||||
"i18next": "^23.7.18",
|
||||
"i18next-browser-languagedetector": "^7.2.0",
|
||||
"npm": "^10.2.5",
|
||||
"path": "^0.12.7",
|
||||
"rammerhead": "https://github.com/holy-unblocker/rammerhead/releases/download/v1.2.41-holy.5/rammerhead-1.2.41-holy.5.tgz",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "3.2.5",
|
||||
"prettier-plugin-astro": "^0.13.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
12
prettier.config.js
Normal file
12
prettier.config.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
const config = {
|
||||
tabWidth: 2,
|
||||
semi: true,
|
||||
trailingComma: "es5",
|
||||
bracketSpacing: true,
|
||||
bracketSameLine: true,
|
||||
arrowParens: "always",
|
||||
plugins: ["prettier-plugin-astro"],
|
||||
printWidth: 100,
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"nav": {
|
||||
"brand": "Alu",
|
||||
"games": "Games",
|
||||
"settings": "Settings"
|
||||
}
|
||||
}
|
||||
"nav": {
|
||||
"brand": "Alu",
|
||||
"games": "Games",
|
||||
"settings": "Settings"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"brand": "アルー",
|
||||
"games": "ゲーム",
|
||||
"settings": "設定"
|
||||
}
|
||||
"brand": "アルー",
|
||||
"games": "ゲーム",
|
||||
"settings": "設定"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@
|
|||
* Ideally, this will be registered under the scope in uv.config.js so it will not need to be modified.
|
||||
* However, if a user changes the location of uv.bundle.js/uv.config.js or sw.js is not relative to them, they will need to modify this script locally.
|
||||
*/
|
||||
importScripts('/uv/uv.bundle.js');
|
||||
importScripts('/uv.config.js');
|
||||
importScripts("/uv/uv.bundle.js");
|
||||
importScripts("/uv.config.js");
|
||||
importScripts(__uv$config.sw);
|
||||
|
||||
self.addEventListener("install", (event) => {
|
||||
self.skipWaiting();
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
const sw = new UVServiceWorker();
|
||||
|
||||
self.addEventListener('fetch', (event) => event.respondWith(sw.fetch(event)));
|
||||
self.addEventListener("fetch", (event) => event.respondWith(sw.fetch(event)));
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
/*global Ultraviolet*/
|
||||
self.__uv$config = {
|
||||
prefix: '/service/',
|
||||
bare: '/bare/',
|
||||
encodeUrl: Ultraviolet.codec.xor.encode,
|
||||
decodeUrl: Ultraviolet.codec.xor.decode,
|
||||
handler: '/uv/uv.handler.js',
|
||||
client: '/uv/uv.client.js',
|
||||
bundle: '/uv/uv.bundle.js',
|
||||
config: '/uv/uv.config.js',
|
||||
sw: '/uv/uv.sw.js',
|
||||
};
|
||||
prefix: "/service/",
|
||||
bare: "/bare/",
|
||||
encodeUrl: Ultraviolet.codec.xor.encode,
|
||||
decodeUrl: Ultraviolet.codec.xor.decode,
|
||||
handler: "/uv/uv.handler.js",
|
||||
client: "/uv/uv.client.js",
|
||||
bundle: "/uv/uv.bundle.js",
|
||||
config: "/uv/uv.config.js",
|
||||
sw: "/uv/uv.sw.js",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,32 +1,32 @@
|
|||
<script>
|
||||
function loadCloak() {
|
||||
let localStorageCloak = localStorage.getItem('alu__selectedCloak');
|
||||
if (localStorageCloak) {
|
||||
let parsedCloak = JSON.parse(localStorageCloak);
|
||||
if (parsedCloak) {
|
||||
if (parsedCloak.name != "None") {
|
||||
document.title = parsedCloak.name
|
||||
let link = document.querySelector("link[rel~='icon']") as HTMLLinkElement;
|
||||
if (!link) {
|
||||
link = document.createElement('link');
|
||||
link.rel = 'icon';
|
||||
}
|
||||
link.href = parsedCloak.icon;
|
||||
document.getElementsByTagName('head')[0].appendChild(link);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Load default cloak
|
||||
let link = document.querySelector("link[rel~='icon']") as HTMLLinkElement;
|
||||
if (!link) {
|
||||
link = document.createElement('link');
|
||||
link.rel = 'icon';
|
||||
}
|
||||
link.href = "/favicon.png";
|
||||
document.getElementsByTagName('head')[0].appendChild(link);
|
||||
function loadCloak() {
|
||||
let localStorageCloak = localStorage.getItem("alu__selectedCloak");
|
||||
if (localStorageCloak) {
|
||||
let parsedCloak = JSON.parse(localStorageCloak);
|
||||
if (parsedCloak) {
|
||||
if (parsedCloak.name != "None") {
|
||||
document.title = parsedCloak.name;
|
||||
let link = document.querySelector("link[rel~='icon']") as HTMLLinkElement;
|
||||
if (!link) {
|
||||
link = document.createElement("link");
|
||||
link.rel = "icon";
|
||||
}
|
||||
link.href = parsedCloak.icon;
|
||||
document.getElementsByTagName("head")[0].appendChild(link);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Load default cloak
|
||||
let link = document.querySelector("link[rel~='icon']") as HTMLLinkElement;
|
||||
if (!link) {
|
||||
link = document.createElement("link");
|
||||
link.rel = "icon";
|
||||
}
|
||||
link.href = "/favicon.png";
|
||||
document.getElementsByTagName("head")[0].appendChild(link);
|
||||
}
|
||||
}
|
||||
|
||||
loadCloak();
|
||||
document.addEventListener("astro:after-swap", loadCloak);
|
||||
</script>
|
||||
loadCloak();
|
||||
document.addEventListener("astro:after-swap", loadCloak);
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,61 +1,65 @@
|
|||
---
|
||||
|
||||
const { buttonNameDefault, dropdownList, id } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="dropdown">
|
||||
<button id={id} class="dropdown-toggle" type="button" data-toggle="dropdown">
|
||||
{buttonNameDefault}
|
||||
<span class="caret"></span></button>
|
||||
<ul class="dropdown-menu" id={id + "-menu"}>
|
||||
<button id={id} class="dropdown-toggle" type="button" data-toggle="dropdown">
|
||||
{buttonNameDefault}
|
||||
<span class="caret"></span></button
|
||||
>
|
||||
<ul class="dropdown-menu" id={id + "-menu"}>
|
||||
{
|
||||
dropdownList.map((item: any) => {
|
||||
return <li class="dropdown-item" data-setting={item.value}>{item.name}</li>
|
||||
})
|
||||
dropdownList.map((item: any) => {
|
||||
return (
|
||||
<li class="dropdown-item" data-setting={item.value}>
|
||||
{item.name}
|
||||
</li>
|
||||
);
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
<style>
|
||||
.dropdown {
|
||||
box-shadow: 4px 6px 15px 0px var(--background-color);
|
||||
border-bottom-left-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
position: relative;
|
||||
}
|
||||
.dropdown-toggle {
|
||||
background-color: var(--accent-color);
|
||||
border: none;
|
||||
color: var(--text-color);
|
||||
padding: 12px 16px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
font-family: 'Varela Round', sans-serif;
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
min-width: 140px;
|
||||
height: 50px;
|
||||
}
|
||||
.dropdown-menu {
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
max-height: 0px; /* Set max-height to 0 instead of height */
|
||||
overflow: hidden;
|
||||
transition: max-height 350ms ease-in-out; /* Use max-height in the transition property */
|
||||
border-bottom-left-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
background-color: var(--dropdown-background-color);
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
.dropdown-item {
|
||||
border-bottom: 1px solid var(--text-color-accent);
|
||||
padding: 10px;
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
.dropdown-item:nth-last-child(1) {
|
||||
border-bottom: none;
|
||||
}
|
||||
</style>
|
||||
.dropdown {
|
||||
box-shadow: 4px 6px 15px 0px var(--background-color);
|
||||
border-bottom-left-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
position: relative;
|
||||
}
|
||||
.dropdown-toggle {
|
||||
background-color: var(--accent-color);
|
||||
border: none;
|
||||
color: var(--text-color);
|
||||
padding: 12px 16px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
font-family: "Varela Round", sans-serif;
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
min-width: 140px;
|
||||
height: 50px;
|
||||
}
|
||||
.dropdown-menu {
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
max-height: 0px; /* Set max-height to 0 instead of height */
|
||||
overflow: hidden;
|
||||
transition: max-height 350ms ease-in-out; /* Use max-height in the transition property */
|
||||
border-bottom-left-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
background-color: var(--dropdown-background-color);
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
.dropdown-item {
|
||||
border-bottom: 1px solid var(--text-color-accent);
|
||||
padding: 10px;
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
.dropdown-item:nth-last-child(1) {
|
||||
border-bottom: none;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,139 +1,66 @@
|
|||
---
|
||||
|
||||
import { getLangFromUrl, useTranslations } from "../i18n/utils"
|
||||
import { getLangFromUrl, useTranslations } from "../i18n/utils";
|
||||
import WaveSVG from "./WaveSVG.astro";
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const t = useTranslations(lang);
|
||||
|
||||
---
|
||||
|
||||
<div id="footer">
|
||||
<div class="footerflex">
|
||||
<div class="footerbrand">
|
||||
<p class="footerlist-heading"><a href="/">{t("footer.brand")}</a></p>
|
||||
<p><a target="_blank" rel="noopener noreferrer" href="https://wearr.dev">{t("footer.madeWithLove")}</a></p>
|
||||
</div>
|
||||
<div class="footerlist">
|
||||
<p class="footerlist-heading">{t("footer.services")}</p>
|
||||
<ul>
|
||||
<li><a target="_blank" rel="noopener noreferrer" href="https://github.com/titaniumnetwork-dev/Ultraviolet">Ultraviolet</a></li>
|
||||
</ul>
|
||||
<div class="footer">
|
||||
<div class="wave-svg-container">
|
||||
<WaveSVG />
|
||||
</div>
|
||||
<div class="footer-top">
|
||||
<div class="footer-title">
|
||||
<h2>{t("footer.brand")}</h2>
|
||||
</div>
|
||||
<div class="footerlist">
|
||||
<p class="footerlist-heading">{t("footer.socials")}</p>
|
||||
<ul>
|
||||
<li><a target="_blank" rel="noopener noreferrer" href="https://github.com/wearrrrr/AlusUnblocker">GitHub</a></li>
|
||||
<li><a target="_blank" rel="noopener noreferrer" href="#">Discord</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="footer-madeby">
|
||||
<a href="https://wearr.dev">{t("footer.madeWithLove")}</a>
|
||||
</div>
|
||||
</div>
|
||||
<p class="copyright">{t("footer.aluProject")} © 2024</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-bottom">
|
||||
<div class="footer-links">
|
||||
<a href="https://titaniumnetwork.org">{t("footer.poweredBy")}</a>
|
||||
</div>
|
||||
|
||||
<div class="footer-copyright">
|
||||
<p>© {t("footer.aluProject")} 2024</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--footer-svg-url: url("/img/aluwaves.svg");
|
||||
}
|
||||
[data-theme="mocha"] {
|
||||
--footer-svg-url: url("/img/mochawaves.svg");
|
||||
}
|
||||
[data-theme="macchiato"] {
|
||||
--footer-svg-url: url("/img/macchiatowaves.svg");
|
||||
}
|
||||
#footer {
|
||||
padding-top: 22vh;
|
||||
background-image: var(--footer-svg-url);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100vw auto;
|
||||
.wave-svg-container {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
z-index: -1;
|
||||
overflow: hidden;
|
||||
height: 300px;
|
||||
filter: brightness(1.5);
|
||||
}
|
||||
|
||||
.footerflex {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
.footer {
|
||||
display: flex;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
}
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
color: var(--text-color);
|
||||
position: relative;
|
||||
padding-top: 100px;
|
||||
gap: 50px;
|
||||
}
|
||||
.footer-top,
|
||||
.footer-bottom {
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.footersocials {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footerflex > div {
|
||||
margin: 25px 50px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
.footerflex > div {
|
||||
margin: 15px 25px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 380px) {
|
||||
.footerflex > div {
|
||||
margin: 5px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.footerbrand div a {
|
||||
font-family: 'Varela Round', sans-serif;
|
||||
color: var(--text-color) !important;
|
||||
.footer-title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.footerbrand p {
|
||||
font-family: 'Varela Round', sans-serif;
|
||||
a {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.footerbrand a {
|
||||
font-family: 'Varela Round', sans-serif;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.footerlist-heading {
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.footerlist ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.footerlist ul > li {
|
||||
padding: 2px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.footerlist ul > li > a {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.footerlist > * {
|
||||
font-family: 'Varela Round', sans-serif;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.footersocials {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.footersocials a {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
padding: 6px;
|
||||
margin: 0 5px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.copyright {
|
||||
color: #D8DEE9;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -3,27 +3,30 @@ const { name, image, slugName } = Astro.props;
|
|||
---
|
||||
|
||||
<div class="game">
|
||||
<a href=`/games/${slugName || name}`><img class="game-img" src=`${image}` alt=""></a>
|
||||
<p class="game-title">{name}</p>
|
||||
<a href=`/games/${slugName || name}`>
|
||||
<img class="game-img" src={image} alt="" />
|
||||
</a>
|
||||
<p class="game-title">{name}</p>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.game {
|
||||
border: 2px solid #D8DEE9;
|
||||
.game {
|
||||
border: 2px solid var(--text-color);
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
.game-img {
|
||||
border-radius: 15px;
|
||||
}
|
||||
.game-img {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
}
|
||||
}
|
||||
|
||||
.game-title {
|
||||
.game-title {
|
||||
color: var(--text-color);
|
||||
text-align: center;
|
||||
max-width: 125px;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,29 +1,29 @@
|
|||
---
|
||||
import { getLangFromUrl, useTranslations } from "../i18n/utils"
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const t = useTranslations(lang);
|
||||
import { getLangFromUrl, useTranslations } from "../i18n/utils";
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const t = useTranslations(lang);
|
||||
---
|
||||
|
||||
<div class="top-header">
|
||||
<div id="title-background" class="title-background">
|
||||
<div class="left">
|
||||
<a href={`/${lang}/`} class="header-item">{t("nav.brand")}</a>
|
||||
</div>
|
||||
<div class="right">
|
||||
<a href={`/${lang}/games/`} class="header-item">{t("nav.games")}</a>
|
||||
<a href={`/${lang}/settings/`} class="header-item">{t("nav.settings")}</a>
|
||||
</div>
|
||||
<div id="title-background" class="title-background">
|
||||
<div class="left">
|
||||
<a href={`/${lang}/`} class="header-item">{t("nav.brand")}</a>
|
||||
</div>
|
||||
<div class="right">
|
||||
<a href={`/${lang}/games/`} class="header-item">{t("nav.games")}</a>
|
||||
<a href={`/${lang}/settings/`} class="header-item">{t("nav.settings")}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.top-header {
|
||||
.top-header {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
transition: 250ms ease-in;
|
||||
}
|
||||
}
|
||||
|
||||
.title-background {
|
||||
.title-background {
|
||||
background-color: var(--accent-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -37,28 +37,29 @@
|
|||
z-index: 10;
|
||||
border-bottom-left-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.left, .right {
|
||||
.left,
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.header-item {
|
||||
.header-item {
|
||||
color: var(--text-color);
|
||||
text-decoration: none;
|
||||
font-size: 22px;
|
||||
transition: 250ms ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
.header-item:hover {
|
||||
.header-item:hover {
|
||||
color: var(--text-color-accent);
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1003px) {
|
||||
@media only screen and (max-width: 1003px) {
|
||||
.title-background {
|
||||
width: 500%;
|
||||
width: 500%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,31 +1,33 @@
|
|||
---
|
||||
const { type, inputName, defaultTextContent, height, placeholder } = Astro.props;
|
||||
|
||||
// typescript brainrot
|
||||
type HTMLInputTypeAttribute = "button" | "checkbox" | "color" | "date" | "datetime-local" | "email" | "file" | "hidden" | "image" | "month" | "number" | "password" | "radio" | "range" | "reset" | "search" | "submit" | "tel" | "text" | "time" | "url" | "week";
|
||||
const { inputName, defaultTextContent, height, placeholder } = Astro.props;
|
||||
|
||||
interface Props {
|
||||
type?: HTMLInputTypeAttribute;
|
||||
inputName: string;
|
||||
defaultTextContent?: string;
|
||||
height: string;
|
||||
placeholder?: string;
|
||||
inputName: string;
|
||||
defaultTextContent?: string;
|
||||
height: string;
|
||||
placeholder?: string;
|
||||
}
|
||||
---
|
||||
|
||||
<input style={`height: ${height}`} id={inputName + "-input"} placeholder={placeholder || ""} value={defaultTextContent || ""} type={type} />
|
||||
<input
|
||||
style={`height: ${height}`}
|
||||
id={inputName + "-input"}
|
||||
placeholder={placeholder || ""}
|
||||
value={defaultTextContent || ""}
|
||||
type="text"
|
||||
/>
|
||||
|
||||
<style>
|
||||
input {
|
||||
width: 100%;
|
||||
border: 2px solid var(--accent-color-brighter);
|
||||
border-radius: 10px;
|
||||
background-color: #1b1b1b;
|
||||
color: var(--text-color);
|
||||
transition: .1s ease-in-out;
|
||||
}
|
||||
input:focus {
|
||||
outline: none;
|
||||
border: 2px solid var(--text-color);
|
||||
}
|
||||
</style>
|
||||
input {
|
||||
width: 100%;
|
||||
border: 2px solid var(--background-highlight);
|
||||
border-radius: 10px;
|
||||
background-color: var(--accent-color);
|
||||
color: var(--text-color);
|
||||
transition: 0.1s ease-in-out;
|
||||
}
|
||||
input:focus {
|
||||
outline: none;
|
||||
border: 2px solid var(--text-color);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
136
src/components/ProxyRegistrar.astro
Normal file
136
src/components/ProxyRegistrar.astro
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
<script src="/uv/uv.bundle.js" transition:persist></script>
|
||||
<script src="/uv.config.js" transition:persist></script>
|
||||
<script>
|
||||
//@ts-nocheck
|
||||
let form = document.querySelector("form");
|
||||
let input = document.querySelector("input");
|
||||
window.navigator.serviceWorker.register("/sw.js", {
|
||||
scope: window.__uv$config.prefix,
|
||||
});
|
||||
document.addEventListener("astro:after-swap", initForm);
|
||||
function initForm() {
|
||||
let formEle = document.querySelector("form");
|
||||
input = document.querySelector("input");
|
||||
if (formEle) formEle.addEventListener("submit", formEventListener);
|
||||
}
|
||||
if (form) {
|
||||
form.addEventListener("submit", formEventListener);
|
||||
}
|
||||
|
||||
async function formEventListener(event) {
|
||||
event.preventDefault();
|
||||
let loadingContent = document.getElementById("loading-content");
|
||||
loadingContent.style.opacity = 1;
|
||||
let url = input.value.trim();
|
||||
if (!isUrl(url)) url = getSearchEngine() + url;
|
||||
else if (!(url.startsWith("https://") || url.startsWith("http://"))) url = "http://" + url;
|
||||
|
||||
let iframe = document.getElementById("proxy-frame");
|
||||
let preference = getProxyPreference();
|
||||
if (preference === "ultraviolet") {
|
||||
iframe.src = window.__uv$config.prefix + window.__uv$config.encodeUrl(url);
|
||||
} else if (preference == "rammerhead") {
|
||||
// Check if rammerhead-session exists in cookies
|
||||
let rammerheadSession = getCookie("rammerhead-session");
|
||||
console.log(rammerheadSession);
|
||||
if (!rammerheadSession) {
|
||||
let session = await fetch("/newsession");
|
||||
let sessionID = await session.text();
|
||||
// Now save it in a cookie that expires in 72 hours.
|
||||
document.cookie = `rammerhead-session=${sessionID}; max-age=${60 * 60 * 72}; path=/`;
|
||||
}
|
||||
iframe.src = `/${getCookie("rammerhead-session")}/${url}`;
|
||||
} else {
|
||||
// Default to UV
|
||||
iframe.src = window.__uv$config.prefix + window.__uv$config.encodeUrl(url);
|
||||
}
|
||||
iframe.style.pointerEvents = "auto";
|
||||
iframe.classList.add("proxy-frame");
|
||||
document.body.appendChild(iframe);
|
||||
iframe.addEventListener("load", () => {
|
||||
let topBar = document.getElementById("top-bar");
|
||||
loadingContent.style.opacity = 0;
|
||||
topBar.innerHTML = "";
|
||||
topBar.classList.add("top-bar");
|
||||
let closeButton = document.createElement("button");
|
||||
closeButton.classList.add("close-button");
|
||||
closeButton.innerText = "Close";
|
||||
closeButton.addEventListener("click", () => {
|
||||
iframe.style.opacity = 0;
|
||||
topBar.style.opacity = 0;
|
||||
iframe.style.pointerEvents = "none";
|
||||
topBar.style.pointerEvents = "none";
|
||||
});
|
||||
let urlText = document.createElement("p");
|
||||
urlText.classList.add("url-text");
|
||||
urlText.innerText = window.__uv$config.decodeUrl(iframe.src.split(__uv$config.prefix)[1]);
|
||||
iframe.style.opacity = 1;
|
||||
topBar.style.opacity = 1;
|
||||
topBar.style.pointerEvents = "auto";
|
||||
topBar.appendChild(closeButton);
|
||||
topBar.appendChild(urlText);
|
||||
document.body.appendChild(topBar);
|
||||
});
|
||||
}
|
||||
|
||||
function isUrl(val = "") {
|
||||
if (/^http(s?):\/\//.test(val) || (val.includes(".") && val.substr(0, 1) !== " ")) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
const value = `; ${document.cookie}`;
|
||||
const parts = value.split(`; ${name}=`);
|
||||
if (parts.length === 2) return parts.pop().split(";").shift();
|
||||
}
|
||||
|
||||
function getSearchEngine() {
|
||||
let localStorageSearchEngine = localStorage.getItem("alu__search_engine");
|
||||
if (!localStorageSearchEngine) {
|
||||
return "https://google.com/search?q=";
|
||||
}
|
||||
switch (JSON.parse(localStorage.getItem("alu__search_engine")).value.toLowerCase()) {
|
||||
case "google": {
|
||||
return "https://google.com/search?q=";
|
||||
}
|
||||
case "bing": {
|
||||
return "https://bing.com/search?q=d";
|
||||
}
|
||||
case "brave": {
|
||||
return "https://search.brave.com/search?q=";
|
||||
}
|
||||
case "searx": {
|
||||
let localStorageURL = localStorage.getItem("alu__searxngUrl");
|
||||
if (localStorageURL) {
|
||||
if (localStorageURL == "") return "https://searxng.site/search?q=";
|
||||
// Ugly hack to remove the trailing slash :)
|
||||
if (localStorageURL.endsWith("/")) localStorageURL = localStorageURL.slice(0, -1);
|
||||
return localStorageURL + "/search?q=";
|
||||
} else return "https://searxng.site/search?q=";
|
||||
}
|
||||
default: {
|
||||
return "https://google.com/search?q=";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getProxyPreference() {
|
||||
let localStorageItem = localStorage.getItem("alu__selectedProxy");
|
||||
|
||||
if (!localStorageItem) return "uv";
|
||||
|
||||
switch (JSON.parse(localStorageItem).value.toLowerCase()) {
|
||||
case "ultraviolet": {
|
||||
return "ultraviolet";
|
||||
}
|
||||
case "rammerhead":
|
||||
return "rammerhead";
|
||||
case "dynamic":
|
||||
// temporary because dynamic is not implemented yet :)
|
||||
return "ultraviolet";
|
||||
default: {
|
||||
return "uv";
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -1,91 +1,118 @@
|
|||
---
|
||||
import Input from "../Input.astro"
|
||||
|
||||
|
||||
const presetCloaks = [
|
||||
{"cloakTitle": "None", "favicon": "/favicon.png"},
|
||||
{"cloakTitle": "Google", "favicon": "https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://google.com&size=128"},
|
||||
{"cloakTitle": "Instructure", "favicon": "https://du11hjcvx0uqb.cloudfront.net/dist/images/favicon-e10d657a73.ico"},
|
||||
{"cloakTitle": "Google Classroom", "favicon": "https://ssl.gstatic.com/classroom/ic_product_classroom_144.png"},
|
||||
{"cloakTitle": "Classlink", "favicon": "https://cdn.classlink.com/production/launchpad/resources/images/favicon/favicon-32x32.png"},
|
||||
{"cloakTitle": "Google Drive", "favicon": "https://ssl.gstatic.com/docs/doclist/images/drive_2022q3_32dp.png"},
|
||||
{"cloakTitle": "Schoology", "favicon": "https://asset-cdn.schoology.com/sites/all/themes/schoology_theme/favicon.ico"}
|
||||
]
|
||||
import Input from "../Input.astro";
|
||||
|
||||
const presetCloaks = [
|
||||
{ cloakTitle: "None", favicon: "/favicon.png" },
|
||||
{
|
||||
cloakTitle: "Google",
|
||||
favicon:
|
||||
"https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://google.com&size=128",
|
||||
},
|
||||
{
|
||||
cloakTitle: "Instructure",
|
||||
favicon: "https://du11hjcvx0uqb.cloudfront.net/dist/images/favicon-e10d657a73.ico",
|
||||
},
|
||||
{
|
||||
cloakTitle: "Google Classroom",
|
||||
favicon: "https://ssl.gstatic.com/classroom/ic_product_classroom_144.png",
|
||||
},
|
||||
{
|
||||
cloakTitle: "Classlink",
|
||||
favicon:
|
||||
"https://cdn.classlink.com/production/launchpad/resources/images/favicon/favicon-32x32.png",
|
||||
},
|
||||
{
|
||||
cloakTitle: "Google Drive",
|
||||
favicon: "https://ssl.gstatic.com/docs/doclist/images/drive_2022q3_32dp.png",
|
||||
},
|
||||
{
|
||||
cloakTitle: "Schoology",
|
||||
favicon: "https://asset-cdn.schoology.com/sites/all/themes/schoology_theme/favicon.ico",
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<div class="settings-container">
|
||||
<div class="cloak-container">
|
||||
<div id="cloak-list">
|
||||
{presetCloaks.map((cloak: any) => {
|
||||
return <div class="cloak-item" data-cloak-name={cloak.cloakTitle} data-cloak-icon={cloak.favicon}><img class="cloak-image" src={cloak.favicon} alt={cloak.cloakTitle}/></div>
|
||||
})}
|
||||
</div>
|
||||
<div class="cloak-custom-override">
|
||||
<Input inputName="cloak-custom-name" placeholder="Custom Name" height="30px" />
|
||||
<Input inputName="cloak-custom-favicon" placeholder="Custom Favicon" height="30px" />
|
||||
<button id="cloak-custom-button">Update Cloak</button>
|
||||
</div>
|
||||
<div class="cloak-container">
|
||||
<div id="cloak-list">
|
||||
{
|
||||
presetCloaks.map((cloak: any) => {
|
||||
return (
|
||||
<div
|
||||
class="cloak-item"
|
||||
data-cloak-name={cloak.cloakTitle}
|
||||
data-cloak-icon={cloak.favicon}>
|
||||
<img class="cloak-image" src={cloak.favicon} alt={cloak.cloakTitle} />
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
<div class="cloak-custom-override">
|
||||
<Input inputName="cloak-custom-name" placeholder="Custom Name" height="30px" />
|
||||
<Input inputName="cloak-custom-favicon" placeholder="Custom Favicon" height="30px" />
|
||||
<button id="cloak-custom-button">Update Cloak</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.cloak-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
#cloak-list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
}
|
||||
.cloak-item {
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
border-radius: 50%;
|
||||
padding: 15px;
|
||||
background-color: var(--dropdown-background-color);
|
||||
border: 3px solid var(--accent-color);
|
||||
cursor: pointer;
|
||||
transition: 250ms ease-in-out;
|
||||
}
|
||||
.cloak-item.selected {
|
||||
/* Make border color brighter */
|
||||
border: 3px solid var(--accent-color-brighter)
|
||||
}
|
||||
.cloak-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.cloak-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
#cloak-list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
}
|
||||
.cloak-item {
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
border-radius: 50%;
|
||||
padding: 15px;
|
||||
background-color: var(--dropdown-background-color);
|
||||
border: 3px solid var(--accent-color);
|
||||
cursor: pointer;
|
||||
transition: 250ms ease-in-out;
|
||||
}
|
||||
.cloak-item.selected {
|
||||
/* Make border color brighter */
|
||||
border: 3px solid var(--accent-color-brighter);
|
||||
}
|
||||
.cloak-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.cloak-custom-override {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
width: 50%;
|
||||
}
|
||||
#cloak-custom-button {
|
||||
margin-top: 6px;
|
||||
height: 25px;
|
||||
border-radius: 10px;
|
||||
background-color: var(--accent-color-brighter);
|
||||
border: 0;
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
.cloak-custom-input {
|
||||
height: 40px;
|
||||
width: 100%;
|
||||
border: 2px solid var(--accent-color-brighter);
|
||||
border-radius: 10px;
|
||||
background-color: #1b1b1b;
|
||||
color: var(--text-color);
|
||||
transition: .1s ease-in-out;
|
||||
}
|
||||
.cloak-custom-input:focus {
|
||||
outline: none;
|
||||
border: 2px solid var(--text-color);
|
||||
}
|
||||
</style>
|
||||
.cloak-custom-override {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
width: 50%;
|
||||
}
|
||||
#cloak-custom-button {
|
||||
margin-top: 6px;
|
||||
height: 25px;
|
||||
border-radius: 10px;
|
||||
background-color: var(--accent-color-brighter);
|
||||
border: 0;
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
.cloak-custom-input {
|
||||
height: 40px;
|
||||
width: 100%;
|
||||
border: 2px solid var(--accent-color-brighter);
|
||||
border-radius: 10px;
|
||||
background-color: #1b1b1b;
|
||||
color: var(--text-color);
|
||||
transition: 0.1s ease-in-out;
|
||||
}
|
||||
.cloak-custom-input:focus {
|
||||
outline: none;
|
||||
border: 2px solid var(--text-color);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,27 +1,49 @@
|
|||
---
|
||||
import { getLangFromUrl, useTranslations } from "../../i18n/utils"
|
||||
import { getLangFromUrl, useTranslations } from "../../i18n/utils";
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const t = useTranslations(lang);
|
||||
|
||||
---
|
||||
|
||||
<div class="settings-container">
|
||||
|
||||
<div class="credits-container">
|
||||
<p class="credit-item">{t("ultraviolet")} - <a href="https://titaniumnetwork.org/">Titanium Network</a></p>
|
||||
<p class="credit-item">{t("settings.credits.japaneseTranslations")} - <a href="https://wearr.dev">wearr</a></p>
|
||||
<p class="credit-item">{t("settings.credits.mochaandmacchiatothemes")} - <a href="">Catppuccin</a></p>
|
||||
</div>
|
||||
|
||||
<div class="credits-container">
|
||||
<p class="credit-item">
|
||||
{t("ultraviolet")} - <a
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
href="https://titaniumnetwork.org/">Titanium Network</a
|
||||
>
|
||||
</p>
|
||||
<p class="credit-item">
|
||||
{t("settings.credits.japaneseTranslations")} - <a
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
href="https://wearr.dev">wearr</a
|
||||
>
|
||||
</p>
|
||||
<p class="credit-item">
|
||||
{t("settings.credits.mochaandmacchiatothemes")} - <a
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
href="https://github.com/catppuccin/catppuccin">Catppuccin</a
|
||||
>
|
||||
</p>
|
||||
<p class="credit-item">
|
||||
Rosé Pine Theme - <a
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
href="https://rosepinetheme.com/">Rosé Pine</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.credit-item {
|
||||
color: var(--text-color);
|
||||
font-size: 18px;
|
||||
}
|
||||
.credit-item > a {
|
||||
color: var(--text-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
.credit-item {
|
||||
color: var(--text-color);
|
||||
font-size: 18px;
|
||||
}
|
||||
.credit-item > a {
|
||||
color: var(--text-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,29 +1,35 @@
|
|||
---
|
||||
import Dropdown from "../Dropdown.astro"
|
||||
import Dropdown from "../Dropdown.astro";
|
||||
|
||||
import { getLangFromUrl, useTranslations } from "../../i18n/utils"
|
||||
import { getLangFromUrl, useTranslations } from "../../i18n/utils";
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const t = useTranslations(lang);
|
||||
|
||||
const themeList = [
|
||||
{"name": t("settings.customization.theme.Alu"), "value": "alu"},
|
||||
{"name": t("settings.customization.theme.Macchiato"), "value": "macchiato"},
|
||||
{"name": t("settings.customization.theme.Mocha"), "value": "mocha"}
|
||||
]
|
||||
{ name: t("settings.customization.theme.Alu"), value: "alu" },
|
||||
{ name: t("settings.customization.theme.Macchiato"), value: "macchiato" },
|
||||
{ name: t("settings.customization.theme.Mocha"), value: "mocha" },
|
||||
{ name: "Rosé Pine", value: "rose_pine" },
|
||||
];
|
||||
|
||||
const languageList = [
|
||||
{"name": "English", "value": "en"},
|
||||
{"name": "日本語", "value": "jp"}
|
||||
]
|
||||
{ name: "English", value: "en" },
|
||||
{ name: "日本語", value: "jp" },
|
||||
];
|
||||
---
|
||||
|
||||
<div class="settings-container">
|
||||
<div class="setting__theme">
|
||||
<label class="setting-label">{t("settings.customization.theme")}</label>
|
||||
<Dropdown buttonNameDefault="Alu" dropdownList={themeList}, id="dropdown__selected-theme" />
|
||||
</div>
|
||||
<div class="setting__language">
|
||||
<label class="setting-label">{t("settings.customization.language")}</label>
|
||||
<Dropdown buttonNameDefault="English" dropdownList={languageList}, id="dropdown__selected-language" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting__theme">
|
||||
<label class="setting-label">{t("settings.customization.theme")}</label>
|
||||
<Dropdown buttonNameDefault="Alu" dropdownList={themeList} , id="dropdown__selected-theme" />
|
||||
</div>
|
||||
<div class="setting__language">
|
||||
<label class="setting-label">{t("settings.customization.language")}</label>
|
||||
<Dropdown
|
||||
buttonNameDefault="English"
|
||||
dropdownList={languageList}
|
||||
,
|
||||
id="dropdown__selected-language"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,51 +1,66 @@
|
|||
---
|
||||
import Input from "../Input.astro"
|
||||
import Dropdown from "../Dropdown.astro"
|
||||
import Input from "../Input.astro";
|
||||
import Dropdown from "../Dropdown.astro";
|
||||
|
||||
import { getLangFromUrl, useTranslations } from "../../i18n/utils"
|
||||
import { getLangFromUrl, useTranslations } from "../../i18n/utils";
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const t = useTranslations(lang);
|
||||
|
||||
const proxyList = [
|
||||
{ "name": t("settings.proxy.auto"), "value": "auto" },
|
||||
{ "name": t("ultraviolet"), "value": "ultraviolet" },
|
||||
{ "name": "Rammerhead", "value": "rammerhead" },
|
||||
{ "name": "Dynamic", "value": "dynamic" }
|
||||
]
|
||||
{ name: t("settings.proxy.auto"), value: "auto" },
|
||||
{ name: t("ultraviolet"), value: "ultraviolet" },
|
||||
{ name: "Rammerhead", value: "rammerhead" },
|
||||
{ name: "Dynamic", value: "dynamic" },
|
||||
];
|
||||
|
||||
const searchEngineList = [
|
||||
{ "name": "Google", "value": "google" },
|
||||
{ "name": "Bing", "value": "bing" },
|
||||
{ "name": "Brave", "value": "brave" },
|
||||
{ "name": "Searx", "value": "searx" }
|
||||
]
|
||||
{ name: "Google", value: "google" },
|
||||
{ name: "Bing", value: "bing" },
|
||||
{ name: "Brave", value: "brave" },
|
||||
{ name: "Searx", value: "searx" },
|
||||
];
|
||||
|
||||
const openPageWith = [
|
||||
{ "name": t("settings.proxy.openPageWith.embed"), "value": "embed" },
|
||||
{ "name": "About:Blank", "value": "about:blank" },
|
||||
{ "name": t("settings.proxy.openPageWith.newTab"), "value": "newTab" },
|
||||
]
|
||||
{ name: t("settings.proxy.openPageWith.embed"), value: "embed" },
|
||||
{ name: "About:Blank", value: "about:blank" },
|
||||
{ name: t("settings.proxy.openPageWith.newTab"), value: "newTab" },
|
||||
];
|
||||
---
|
||||
|
||||
<div class="settings-container">
|
||||
<div class="setting__selected-proxy">
|
||||
<label class="setting-label">{t("settings.proxy.selectedProxy")}</label>
|
||||
<Dropdown buttonNameDefault="Ultraviolet" dropdownList={proxyList}, id="dropdown__selected-proxy" />
|
||||
</div>
|
||||
<div class="setting__search-engine">
|
||||
<label class="setting-label">{t("settings.proxy.searchEngine")}</label>
|
||||
<Dropdown buttonNameDefault="Google" dropdownList={searchEngineList}, id="dropdown__search-engine" />
|
||||
</div>
|
||||
<div class="setting__open_with">
|
||||
<label class="setting-label">{t("settings.proxy.openPageWith")}</label>
|
||||
<Dropdown buttonNameDefault={t("settings.proxy.openPageWith.embed")} dropdownList={openPageWith}, id="dropdown__open-with" />
|
||||
</div>
|
||||
<div class="setting__bare-url">
|
||||
<label class="setting-label" for="bare-url-input">{t("settings.proxy.bareURL")}</label>
|
||||
<Input inputName="bare-url" height="50px" />
|
||||
</div>
|
||||
<div class="setting__selected-proxy">
|
||||
<label class="setting-label">{t("settings.proxy.selectedProxy")}</label>
|
||||
<Dropdown
|
||||
buttonNameDefault="Ultraviolet"
|
||||
dropdownList={proxyList}
|
||||
,
|
||||
id="dropdown__selected-proxy"
|
||||
/>
|
||||
</div>
|
||||
<div class="setting__search-engine">
|
||||
<label class="setting-label">{t("settings.proxy.searchEngine")}</label>
|
||||
<Dropdown
|
||||
buttonNameDefault="Google"
|
||||
dropdownList={searchEngineList}
|
||||
,
|
||||
id="dropdown__search-engine"
|
||||
/>
|
||||
</div>
|
||||
<div class="setting__open_with">
|
||||
<label class="setting-label">{t("settings.proxy.openPageWith")}</label>
|
||||
<Dropdown
|
||||
buttonNameDefault={t("settings.proxy.openPageWith.embed")}
|
||||
dropdownList={openPageWith}
|
||||
,
|
||||
id="dropdown__open-with"
|
||||
/>
|
||||
</div>
|
||||
<div class="setting__bare-url">
|
||||
<label class="setting-label" for="bare-url-input">{t("settings.proxy.bareURL")}</label>
|
||||
<Input inputName="bare-url" height="50px" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting__searxng-url">
|
||||
<label for="searxng-url-input" class="setting-label">{t("settings.proxy.searxngURL")}</label>
|
||||
<Input height="50px" inputName="searxng-url" defaultTextContent="https://searxng.site/" />
|
||||
</div>
|
||||
<label for="searxng-url-input" class="setting-label">{t("settings.proxy.searxngURL")}</label>
|
||||
<Input height="50px" inputName="searxng-url" defaultTextContent="https://searxng.site/" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import ProxyTab from "./SettingsContent/ProxyTab.astro";
|
||||
import CustomizationTab from "./SettingsContent/CustomizationTab.astro";
|
||||
|
||||
import { getLangFromUrl, useTranslations } from "../i18n/utils"
|
||||
import { getLangFromUrl, useTranslations } from "../i18n/utils";
|
||||
import CloakingTab from "./SettingsContent/CloakingTab.astro";
|
||||
import CreditsTab from "./SettingsContent/CreditsTab.astro";
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
|
|
@ -10,446 +10,472 @@ const t = useTranslations(lang);
|
|||
---
|
||||
|
||||
<div class="content-hidden">
|
||||
<div id="content-setting-tab-proxy">
|
||||
<h1 class="content-setting-header">{t("settings.proxy")}</h1>
|
||||
<ProxyTab />
|
||||
|
||||
</div>
|
||||
<div id="content-setting-tab-customization">
|
||||
<h1 class="content-setting-header">{t("settings.customization")}</h1>
|
||||
<CustomizationTab />
|
||||
</div>
|
||||
<div id="content-setting-tab-cloaking">
|
||||
<h1 class="content-setting-header">{t("settings.cloaking")}</h1>
|
||||
<p class="content-setting-subtext">{t("settings.cloaking.subtext")}</p>
|
||||
<CloakingTab />
|
||||
</div>
|
||||
<div id="content-setting-tab-credits">
|
||||
<h1 class="content-setting-header">{t("settings.credits")}</h1>
|
||||
<CreditsTab />
|
||||
</div>
|
||||
<div id="content-setting-tab-proxy">
|
||||
<h1 class="content-setting-header">{t("settings.proxy")}</h1>
|
||||
<ProxyTab />
|
||||
</div>
|
||||
<div id="content-setting-tab-customization">
|
||||
<h1 class="content-setting-header">{t("settings.customization")}</h1>
|
||||
<CustomizationTab />
|
||||
</div>
|
||||
<div id="content-setting-tab-cloaking">
|
||||
<h1 class="content-setting-header">{t("settings.cloaking")}</h1>
|
||||
<p class="content-setting-subtext">{t("settings.cloaking.subtext")}</p>
|
||||
<CloakingTab />
|
||||
</div>
|
||||
<div id="content-setting-tab-credits">
|
||||
<h1 class="content-setting-header">{t("settings.credits")}</h1>
|
||||
<CreditsTab />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="popup">
|
||||
<div class="tabs">
|
||||
<input type="radio" id="setting-tab-proxy" class="setting-tab" name="tab" checked="true">
|
||||
<label for="setting-tab-proxy">Proxy</label>
|
||||
<input type="radio" id="setting-tab-customization" class="setting-tab" name="tab">
|
||||
<label for="setting-tab-customization">Customization</label>
|
||||
<input type="radio" id="setting-tab-cloaking" class="setting-tab" name="tab">
|
||||
<label for="setting-tab-cloaking">Cloaking</label>
|
||||
<input type="radio" id="setting-tab-credits" class="setting-tab" name="tab">
|
||||
<label for="setting-tab-credits">Credits</label>
|
||||
<div class="marker">
|
||||
<div id="top"></div>
|
||||
<div id="bottom"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="current-content">
|
||||
|
||||
<div class="tabs">
|
||||
<input type="radio" id="setting-tab-proxy" class="setting-tab" name="tab" checked="true" />
|
||||
<label for="setting-tab-proxy">Proxy</label>
|
||||
<input type="radio" id="setting-tab-customization" class="setting-tab" name="tab" />
|
||||
<label for="setting-tab-customization">Customization</label>
|
||||
<input type="radio" id="setting-tab-cloaking" class="setting-tab" name="tab" />
|
||||
<label for="setting-tab-cloaking">Cloaking</label>
|
||||
<input type="radio" id="setting-tab-credits" class="setting-tab" name="tab" />
|
||||
<label for="setting-tab-credits">Credits</label>
|
||||
<div class="marker">
|
||||
<div id="top"></div>
|
||||
<div id="bottom"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script is:inline>
|
||||
document.addEventListener("astro:before-swap", () => {
|
||||
window.currentlySelectedTab = ""
|
||||
document.removeEventListener('setting-tabChange', determineListener)
|
||||
})
|
||||
window.currentlySelectedTab;
|
||||
window.loadedContentStorage = {}
|
||||
<div id="current-content"></div>
|
||||
</div>
|
||||
<script is:inline>
|
||||
document.addEventListener("astro:before-swap", () => {
|
||||
window.currentlySelectedTab = "";
|
||||
document.removeEventListener("setting-tabChange", determineListener);
|
||||
});
|
||||
window.currentlySelectedTab;
|
||||
window.loadedContentStorage = {};
|
||||
|
||||
Array.from(document.getElementsByClassName('setting-tab')).forEach((tab)=>{
|
||||
let contentToLoad = document.getElementById('content-' + tab.id)
|
||||
if (contentToLoad) {
|
||||
window.loadedContentStorage[tab.id] = contentToLoad.innerHTML
|
||||
contentToLoad.remove()
|
||||
}
|
||||
Array.from(document.getElementsByClassName("setting-tab")).forEach((tab) => {
|
||||
let contentToLoad = document.getElementById("content-" + tab.id);
|
||||
if (contentToLoad) {
|
||||
window.loadedContentStorage[tab.id] = contentToLoad.innerHTML;
|
||||
contentToLoad.remove();
|
||||
}
|
||||
|
||||
tab.addEventListener('click', (event) => {
|
||||
loadContent(event.target.id)
|
||||
})
|
||||
})
|
||||
tab.addEventListener("click", (event) => {
|
||||
loadContent(event.target.id);
|
||||
});
|
||||
});
|
||||
|
||||
function loadContent(tabID) {
|
||||
if (window.currentlySelectedTab == tabID) return
|
||||
else window.currentlySelectedTab = tabID
|
||||
let currentContent = document.getElementById('current-content')
|
||||
if (currentContent) {
|
||||
currentContent.style.opacity = '0'
|
||||
setTimeout(() => {
|
||||
currentContent.innerHTML = window.loadedContentStorage[tabID]
|
||||
currentContent.style.opacity = '1'
|
||||
document.dispatchEvent(new CustomEvent('setting-tabChange', {detail: tabID }))
|
||||
document.dispatchEvent(new CustomEvent('setting-tabLoad', {detail: tabID }))
|
||||
}, 250);
|
||||
function loadContent(tabID) {
|
||||
if (window.currentlySelectedTab == tabID) return;
|
||||
else window.currentlySelectedTab = tabID;
|
||||
let currentContent = document.getElementById("current-content");
|
||||
if (currentContent) {
|
||||
currentContent.style.opacity = "0";
|
||||
setTimeout(() => {
|
||||
currentContent.innerHTML = window.loadedContentStorage[tabID];
|
||||
currentContent.style.opacity = "1";
|
||||
document.dispatchEvent(new CustomEvent("setting-tabChange", { detail: tabID }));
|
||||
document.dispatchEvent(new CustomEvent("setting-tabLoad", { detail: tabID }));
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
|
||||
function addDropdownListener() {
|
||||
let dropdown_toggles = document.getElementsByClassName("dropdown-toggle");
|
||||
Array.from(dropdown_toggles).forEach((toggle) => {
|
||||
toggle.addEventListener("click", () => {
|
||||
let dropdown = document.getElementById(toggle.id + "-menu");
|
||||
if (dropdown) {
|
||||
if (dropdown.style.maxHeight == "0px" || dropdown.style.maxHeight == "") {
|
||||
dropdown.style.maxHeight = dropdown.scrollHeight + "px";
|
||||
toggle.style.borderRadius = "10px 10px 0 0";
|
||||
} else {
|
||||
dropdown.style.maxHeight = "0px";
|
||||
setTimeout(() => {
|
||||
toggle.style.borderRadius = "10px";
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function addDropdownListener() {
|
||||
let dropdown_toggles = document.getElementsByClassName('dropdown-toggle')
|
||||
Array.from(dropdown_toggles).forEach((toggle) => {
|
||||
toggle.addEventListener('click', () => {
|
||||
let dropdown = document.getElementById(toggle.id + "-menu")
|
||||
if (dropdown) {
|
||||
if (dropdown.style.maxHeight == '0px' || dropdown.style.maxHeight == '') {
|
||||
dropdown.style.maxHeight = dropdown.scrollHeight + 'px';
|
||||
toggle.style.borderRadius = '10px 10px 0 0';
|
||||
} else {
|
||||
dropdown.style.maxHeight = '0px';
|
||||
setTimeout(() => {
|
||||
toggle.style.borderRadius = '10px';
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
function determineListener(event) {
|
||||
if (event.detail == "setting-tab-proxy") {
|
||||
addDropdownListener();
|
||||
} else if (event.detail == "setting-tab-customization") {
|
||||
addDropdownListener();
|
||||
}
|
||||
}
|
||||
|
||||
function determineListener(event) {
|
||||
if (event.detail == "setting-tab-proxy") {
|
||||
addDropdownListener()
|
||||
} else if (event.detail == "setting-tab-customization") {
|
||||
addDropdownListener()
|
||||
function closeDropdown(dropdownID) {
|
||||
let dropdown = document.getElementById(dropdownID);
|
||||
if (dropdown) {
|
||||
dropdown.style.maxHeight = "0px";
|
||||
setTimeout(() => {
|
||||
let dropdown_toggle = document.getElementById(dropdownID.replace("-menu", ""));
|
||||
dropdown_toggle.style.borderRadius = "10px";
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
function getLocalStorageValue(localStorageItem, dropdownID) {
|
||||
// I was kinda dumb for not doing this earlier.
|
||||
let dropdown = document.getElementById(dropdownID);
|
||||
let dropdownMenu = document.getElementById(dropdownID + "-menu");
|
||||
|
||||
if (dropdown && dropdownMenu) {
|
||||
// Now we find the child that matches localStorageItem.value.
|
||||
let dropdownItem = Array.from(dropdownMenu.children).find((item) => {
|
||||
return JSON.parse(localStorage.getItem(localStorageItem)).value == item.dataset.setting;
|
||||
});
|
||||
// Now set the inner text to the name in the dropdownItem.
|
||||
return dropdownItem.innerText;
|
||||
}
|
||||
}
|
||||
|
||||
function applySavedLocalStorage(localStorageItem, dropdownID) {
|
||||
if (localStorage.getItem(localStorageItem)) {
|
||||
let dropdown_toggle = document.getElementById(dropdownID);
|
||||
if (dropdown_toggle) {
|
||||
dropdown_toggle.innerText = getLocalStorageValue(localStorageItem, dropdownID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function closeDropdown(dropdownID) {
|
||||
let dropdown = document.getElementById(dropdownID)
|
||||
if (dropdown) {
|
||||
dropdown.style.maxHeight = '0px';
|
||||
setTimeout(() => {
|
||||
let dropdown_toggle = document.getElementById(dropdownID.replace('-menu', ''));
|
||||
dropdown_toggle.style.borderRadius = '10px';
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
function getLocalStorageValue(localStorageItem, dropdownID) {
|
||||
// I was kinda dumb for not doing this earlier.
|
||||
let dropdown = document.getElementById(dropdownID);
|
||||
let dropdownMenu = document.getElementById(dropdownID + "-menu");
|
||||
|
||||
if (dropdown && dropdownMenu) {
|
||||
// Now we find the child that matches localStorageItem.value.
|
||||
let dropdownItem = Array.from(dropdownMenu.children).find((item) => {
|
||||
return JSON.parse(localStorage.getItem(localStorageItem)).value == item.dataset.setting
|
||||
})
|
||||
// Now set the inner text to the name in the dropdownItem.
|
||||
return dropdownItem.innerText
|
||||
}
|
||||
}
|
||||
|
||||
function applySavedLocalStorage(localStorageItem, dropdownID) {
|
||||
if (localStorage.getItem(localStorageItem)) {
|
||||
let dropdown_toggle = document.getElementById(dropdownID);
|
||||
if (dropdown_toggle) {
|
||||
dropdown_toggle.innerText = getLocalStorageValue(localStorageItem, dropdownID)
|
||||
function applyDropdownEventListeners(item, dropdownID, localStorageItem, optionalCallback) {
|
||||
Array.from(item.children).forEach((item) => {
|
||||
item.addEventListener("click", () => {
|
||||
let localStorageItemContent = {
|
||||
name: item.innerText,
|
||||
value: item.dataset.setting,
|
||||
};
|
||||
localStorage.setItem(localStorageItem, JSON.stringify(localStorageItemContent));
|
||||
applySavedLocalStorage(localStorageItem, dropdownID);
|
||||
closeDropdown(item.parentElement.id);
|
||||
if (typeof optionalCallback == "function") {
|
||||
optionalCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
// Array.from(item.children).forEach((item) => {
|
||||
// item.addEventListener('click', () => {
|
||||
// localStorage.setItem(localStorageItem, item.dataset.setting)
|
||||
// applySavedLocalStorage(localStorageItem, dropdownID)
|
||||
// closeDropdown(item.parentElement.id);
|
||||
|
||||
function applyDropdownEventListeners(item, dropdownID, localStorageItem, optionalCallback) {
|
||||
Array.from(item.children).forEach((item) => {
|
||||
item.addEventListener('click', () => {
|
||||
let localStorageItemContent = {
|
||||
"name": item.innerText,
|
||||
"value": item.dataset.setting,
|
||||
}
|
||||
localStorage.setItem(localStorageItem, JSON.stringify(localStorageItemContent))
|
||||
applySavedLocalStorage(localStorageItem, dropdownID)
|
||||
closeDropdown(item.parentElement.id);
|
||||
if (typeof optionalCallback == "function") {
|
||||
optionalCallback();
|
||||
}
|
||||
})
|
||||
})
|
||||
// Array.from(item.children).forEach((item) => {
|
||||
// item.addEventListener('click', () => {
|
||||
// localStorage.setItem(localStorageItem, item.dataset.setting)
|
||||
// applySavedLocalStorage(localStorageItem, dropdownID)
|
||||
// closeDropdown(item.parentElement.id);
|
||||
// if (typeof optionalCallback == "function") {
|
||||
// optionalCallback();
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
}
|
||||
|
||||
// if (typeof optionalCallback == "function") {
|
||||
// optionalCallback();
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
}
|
||||
function applyInputListeners(item, localStorageItem) {
|
||||
item.addEventListener("input", () => {
|
||||
localStorage.setItem(localStorageItem, item.value);
|
||||
});
|
||||
}
|
||||
|
||||
function applyInputListeners(item, localStorageItem) {
|
||||
item.addEventListener('input', () => {
|
||||
localStorage.setItem(localStorageItem, item.value)
|
||||
})
|
||||
}
|
||||
document.addEventListener("setting-tabChange", determineListener);
|
||||
|
||||
document.addEventListener('setting-tabChange', determineListener)
|
||||
loadContent("setting-tab-proxy");
|
||||
|
||||
loadContent('setting-tab-proxy')
|
||||
function setupCustomizationSettings() {
|
||||
applySavedLocalStorage("alu__selectedTheme", "dropdown__selected-theme");
|
||||
applySavedLocalStorage("alu__selectedLanguage", "dropdown__selected-language");
|
||||
let themeDropdown = document.getElementById("dropdown__selected-theme-menu");
|
||||
let languageDropdown = document.getElementById("dropdown__selected-language-menu");
|
||||
applyDropdownEventListeners(
|
||||
themeDropdown,
|
||||
"dropdown__selected-theme",
|
||||
"alu__selectedTheme",
|
||||
changeTheme
|
||||
);
|
||||
applyDropdownEventListeners(
|
||||
languageDropdown,
|
||||
"dropdown__selected-language",
|
||||
"alu__selectedLanguage",
|
||||
navigateToNewLangaugePage
|
||||
);
|
||||
}
|
||||
|
||||
function setupCustomizationSettings() {
|
||||
applySavedLocalStorage('alu__selectedTheme', 'dropdown__selected-theme');
|
||||
applySavedLocalStorage('alu__selectedLanguage', 'dropdown__selected-language');
|
||||
let themeDropdown = document.getElementById('dropdown__selected-theme-menu')
|
||||
let languageDropdown = document.getElementById('dropdown__selected-language-menu')
|
||||
applyDropdownEventListeners(themeDropdown, 'dropdown__selected-theme', 'alu__selectedTheme', changeTheme);
|
||||
applyDropdownEventListeners(languageDropdown, 'dropdown__selected-language', 'alu__selectedLanguage', navigateToNewLangaugePage);
|
||||
}
|
||||
function setupCloakingSettings() {
|
||||
Array.from(document.getElementById("cloak-list").children).forEach((cloak) => {
|
||||
cloak.addEventListener("click", () => {
|
||||
let cloakName = cloak.dataset.cloakName;
|
||||
let cloakIcon = cloak.dataset.cloakIcon;
|
||||
|
||||
function setupCloakingSettings() {
|
||||
Array.from(document.getElementById('cloak-list').children).forEach((cloak) => {
|
||||
cloak.addEventListener('click', () => {
|
||||
let cloakName = cloak.dataset.cloakName
|
||||
let cloakIcon = cloak.dataset.cloakIcon
|
||||
|
||||
let localStorageItem = {
|
||||
"name": cloakName,
|
||||
"icon": cloakIcon,
|
||||
"isCustom": false,
|
||||
}
|
||||
localStorage.setItem('alu__selectedCloak', JSON.stringify(localStorageItem))
|
||||
|
||||
if (cloakName == "None") {
|
||||
localStorage.removeItem('alu__selectedCloak')
|
||||
cloakName = "Settings | Alu"
|
||||
cloakIcon = "/favicon.png"
|
||||
}
|
||||
let link = document.querySelector("link[rel~='icon']");
|
||||
if (!link) {
|
||||
link = document.createElement('link');
|
||||
link.rel = 'icon';
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
link.href = cloakIcon;
|
||||
document.title = cloakName;
|
||||
|
||||
if (!cloak.classList.contains("selected")) {
|
||||
Array.from(document.getElementById('cloak-list').children).forEach((cloak2) => {
|
||||
cloak2.classList.remove('selected')
|
||||
})
|
||||
cloak.classList.add('selected')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
let customNameInput = document.getElementById('cloak-custom-name-input')
|
||||
let customFaviconInput = document.getElementById('cloak-custom-favicon-input')
|
||||
if (localStorage.getItem('alu__selectedCloak')) {
|
||||
let selectedCloak = JSON.parse(localStorage.getItem('alu__selectedCloak'))
|
||||
if (selectedCloak.isCustom) {
|
||||
customNameInput.value = selectedCloak.name
|
||||
customFaviconInput.value = selectedCloak.icon
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('cloak-custom-button').addEventListener("click", () => {
|
||||
let cloakName = document.getElementById('cloak-custom-name-input').value
|
||||
let cloakIcon = document.getElementById('cloak-custom-favicon-input').value
|
||||
let localStorageItem = {
|
||||
"name": cloakName,
|
||||
"icon": cloakIcon,
|
||||
"isCustom": true,
|
||||
}
|
||||
localStorage.setItem('alu__selectedCloak', JSON.stringify(localStorageItem))
|
||||
name: cloakName,
|
||||
icon: cloakIcon,
|
||||
isCustom: false,
|
||||
};
|
||||
localStorage.setItem("alu__selectedCloak", JSON.stringify(localStorageItem));
|
||||
|
||||
if (cloakName == "None") {
|
||||
localStorage.removeItem('alu__selectedCloak')
|
||||
cloakName = "Settings | Alu"
|
||||
cloakIcon = "/favicon.png"
|
||||
}
|
||||
localStorage.removeItem("alu__selectedCloak");
|
||||
cloakName = "Settings | Alu";
|
||||
cloakIcon = "/favicon.png";
|
||||
}
|
||||
let link = document.querySelector("link[rel~='icon']");
|
||||
if (!link) {
|
||||
link = document.createElement('link');
|
||||
link.rel = 'icon';
|
||||
document.head.appendChild(link);
|
||||
link = document.createElement("link");
|
||||
link.rel = "icon";
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
link.href = cloakIcon;
|
||||
document.title = cloakName;
|
||||
})
|
||||
}
|
||||
|
||||
function changeTheme() {
|
||||
let theme = JSON.parse(localStorage.getItem('alu__selectedTheme')).value
|
||||
if (theme) {
|
||||
document.documentElement.setAttribute('data-theme', theme.toLowerCase())
|
||||
let footer = document.getElementById('footer');
|
||||
if (footer) {
|
||||
footer.dataset.theme = theme.toLowerCase();
|
||||
if (!cloak.classList.contains("selected")) {
|
||||
Array.from(document.getElementById("cloak-list").children).forEach((cloak2) => {
|
||||
cloak2.classList.remove("selected");
|
||||
});
|
||||
cloak.classList.add("selected");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let customNameInput = document.getElementById("cloak-custom-name-input");
|
||||
let customFaviconInput = document.getElementById("cloak-custom-favicon-input");
|
||||
if (localStorage.getItem("alu__selectedCloak")) {
|
||||
let selectedCloak = JSON.parse(localStorage.getItem("alu__selectedCloak"));
|
||||
if (selectedCloak.isCustom) {
|
||||
customNameInput.value = selectedCloak.name;
|
||||
customFaviconInput.value = selectedCloak.icon;
|
||||
}
|
||||
}
|
||||
|
||||
function setupSettings(event) {
|
||||
if (event.detail == "setting-tab-proxy") {
|
||||
applySavedLocalStorage('alu__selectedProxy', 'dropdown__selected-proxy');
|
||||
applySavedLocalStorage('alu__search_engine', 'dropdown__search-engine');
|
||||
applySavedLocalStorage("alu__selectedOpenWith", 'dropdown__open-with');
|
||||
let selectedProxyDropdown = document.getElementById('dropdown__selected-proxy-menu')
|
||||
let searchEngineDropdown = document.getElementById('dropdown__search-engine-menu')
|
||||
let openWithDropdown = document.getElementById('dropdown__open-with-menu')
|
||||
let bareUrlInput = document.getElementById('bare-url-input')
|
||||
let searxngUrlInput = document.getElementById('searxng-url-input')
|
||||
let savedSearxngUrl = localStorage.getItem("alu__searxngUrl")
|
||||
if (savedSearxngUrl != undefined) {
|
||||
if (savedSearxngUrl == "") localStorage.setItem("alu__searxngUrl", "https://searxng.site/")
|
||||
searxngUrlInput.value = localStorage.getItem("alu__searxngUrl")
|
||||
}
|
||||
// Proxy settings
|
||||
applyInputListeners(bareUrlInput, 'alu__bareUrl')
|
||||
applyInputListeners(searxngUrlInput, 'alu__searxngUrl')
|
||||
applyDropdownEventListeners(searchEngineDropdown, 'dropdown__search-engine', 'alu__search_engine', checkSearxng);
|
||||
applyDropdownEventListeners(selectedProxyDropdown, 'dropdown__selected-proxy', 'alu__selectedProxy');
|
||||
applyDropdownEventListeners(openWithDropdown, 'dropdown__open-with', 'alu__selectedOpenWith');
|
||||
if (localStorage.getItem('bareUrl')) {
|
||||
bareUrlInput.value = localStorage.getItem('bareUrl')
|
||||
} else {
|
||||
bareUrlInput.value = '/bare/'
|
||||
}
|
||||
checkSearxng();
|
||||
} else if (event.detail == "setting-tab-customization") {
|
||||
setupCustomizationSettings();
|
||||
} else if (event.detail == "setting-tab-cloaking") {
|
||||
setupCloakingSettings();
|
||||
}
|
||||
}
|
||||
document.getElementById("cloak-custom-button").addEventListener("click", () => {
|
||||
let cloakName = document.getElementById("cloak-custom-name-input").value;
|
||||
let cloakIcon = document.getElementById("cloak-custom-favicon-input").value;
|
||||
let localStorageItem = {
|
||||
name: cloakName,
|
||||
icon: cloakIcon,
|
||||
isCustom: true,
|
||||
};
|
||||
localStorage.setItem("alu__selectedCloak", JSON.stringify(localStorageItem));
|
||||
if (cloakName == "None") {
|
||||
localStorage.removeItem("alu__selectedCloak");
|
||||
cloakName = "Settings | Alu";
|
||||
cloakIcon = "/favicon.png";
|
||||
}
|
||||
let link = document.querySelector("link[rel~='icon']");
|
||||
if (!link) {
|
||||
link = document.createElement("link");
|
||||
link.rel = "icon";
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
link.href = cloakIcon;
|
||||
document.title = cloakName;
|
||||
});
|
||||
}
|
||||
|
||||
function checkSearxng() {
|
||||
// This function checks if the "searxng" option was clicked, display an additional option if so.
|
||||
if (localStorage.getItem("alu__search_engine")) {
|
||||
if (JSON.parse(localStorage.getItem("alu__search_engine")).value.toLowerCase() == "searx") {
|
||||
document.getElementsByClassName('setting__searxng-url')[0].style.opacity = '1'
|
||||
} else {
|
||||
document.getElementsByClassName('setting__searxng-url')[0].style.opacity = '0'
|
||||
}
|
||||
function changeTheme() {
|
||||
let theme = JSON.parse(localStorage.getItem("alu__selectedTheme")).value;
|
||||
if (theme) {
|
||||
document.documentElement.setAttribute("data-theme", theme.toLowerCase());
|
||||
let footer = document.getElementById("footer");
|
||||
if (footer) {
|
||||
footer.dataset.theme = theme.toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('setting-tabLoad', setupSettings)
|
||||
function setupSettings(event) {
|
||||
if (event.detail == "setting-tab-proxy") {
|
||||
applySavedLocalStorage("alu__selectedProxy", "dropdown__selected-proxy");
|
||||
applySavedLocalStorage("alu__search_engine", "dropdown__search-engine");
|
||||
applySavedLocalStorage("alu__selectedOpenWith", "dropdown__open-with");
|
||||
let selectedProxyDropdown = document.getElementById("dropdown__selected-proxy-menu");
|
||||
let searchEngineDropdown = document.getElementById("dropdown__search-engine-menu");
|
||||
let openWithDropdown = document.getElementById("dropdown__open-with-menu");
|
||||
let bareUrlInput = document.getElementById("bare-url-input");
|
||||
let searxngUrlInput = document.getElementById("searxng-url-input");
|
||||
let savedSearxngUrl = localStorage.getItem("alu__searxngUrl");
|
||||
if (savedSearxngUrl != undefined) {
|
||||
if (savedSearxngUrl == "") localStorage.setItem("alu__searxngUrl", "https://searxng.site/");
|
||||
searxngUrlInput.value = localStorage.getItem("alu__searxngUrl");
|
||||
}
|
||||
// Proxy settings
|
||||
applyInputListeners(bareUrlInput, "alu__bareUrl");
|
||||
applyInputListeners(searxngUrlInput, "alu__searxngUrl");
|
||||
applyDropdownEventListeners(
|
||||
searchEngineDropdown,
|
||||
"dropdown__search-engine",
|
||||
"alu__search_engine",
|
||||
checkSearxng
|
||||
);
|
||||
applyDropdownEventListeners(
|
||||
selectedProxyDropdown,
|
||||
"dropdown__selected-proxy",
|
||||
"alu__selectedProxy"
|
||||
);
|
||||
applyDropdownEventListeners(openWithDropdown, "dropdown__open-with", "alu__selectedOpenWith");
|
||||
if (localStorage.getItem("bareUrl")) {
|
||||
bareUrlInput.value = localStorage.getItem("bareUrl");
|
||||
} else {
|
||||
bareUrlInput.value = "/bare/";
|
||||
}
|
||||
checkSearxng();
|
||||
} else if (event.detail == "setting-tab-customization") {
|
||||
setupCustomizationSettings();
|
||||
} else if (event.detail == "setting-tab-cloaking") {
|
||||
setupCloakingSettings();
|
||||
}
|
||||
}
|
||||
|
||||
function navigateToNewLangaugePage() {
|
||||
let value = JSON.parse(localStorage.getItem("alu__selectedLanguage")).value
|
||||
let currentLanguage = window.location.pathname.split("/")[1]
|
||||
// Do nothing.. because we're already on the page.
|
||||
if (value == currentLanguage) return;
|
||||
switch (value) {
|
||||
case "en":
|
||||
window.location.href = "/en/settings/"
|
||||
break;
|
||||
case "jp":
|
||||
window.location.href = "/jp/settings/"
|
||||
break;
|
||||
function checkSearxng() {
|
||||
// This function checks if the "searxng" option was clicked, display an additional option if so.
|
||||
if (localStorage.getItem("alu__search_engine")) {
|
||||
if (JSON.parse(localStorage.getItem("alu__search_engine")).value.toLowerCase() == "searx") {
|
||||
document.getElementsByClassName("setting__searxng-url")[0].style.opacity = "1";
|
||||
} else {
|
||||
document.getElementsByClassName("setting__searxng-url")[0].style.opacity = "0";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("setting-tabLoad", setupSettings);
|
||||
|
||||
function navigateToNewLangaugePage() {
|
||||
let value = JSON.parse(localStorage.getItem("alu__selectedLanguage")).value;
|
||||
let currentLanguage = window.location.pathname.split("/")[1];
|
||||
// Do nothing.. because we're already on the page.
|
||||
if (value == currentLanguage) return;
|
||||
switch (value) {
|
||||
case "en":
|
||||
window.location.href = "/en/settings/";
|
||||
break;
|
||||
case "jp":
|
||||
window.location.href = "/jp/settings/";
|
||||
break;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style is:global>
|
||||
.content-hidden {
|
||||
.content-hidden {
|
||||
display: none;
|
||||
}
|
||||
#current-content {
|
||||
}
|
||||
#current-content {
|
||||
transition: opacity 250ms ease-in-out;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.settings-container {
|
||||
}
|
||||
.settings-container {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
.content-setting-header {
|
||||
color: var(--text-color);
|
||||
font-weight: 400;
|
||||
}
|
||||
.content-setting-subtext {
|
||||
font-size: 20px;
|
||||
color: var(--text-color-accent);
|
||||
}
|
||||
}
|
||||
.content-setting-header {
|
||||
color: var(--text-color);
|
||||
font-weight: 400;
|
||||
}
|
||||
.content-setting-subtext {
|
||||
font-size: 20px;
|
||||
color: var(--text-color-accent);
|
||||
}
|
||||
|
||||
.setting-label {
|
||||
color: var(--text-color);
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
/* annoying stuff with label elements. */
|
||||
display: block;
|
||||
opacity: 1.0;
|
||||
margin-block: 1em;
|
||||
margin-inline: 0;
|
||||
user-select: none;
|
||||
width: 100%;
|
||||
cursor: auto;
|
||||
}
|
||||
.setting-label {
|
||||
color: var(--text-color);
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
/* annoying stuff with label elements. */
|
||||
display: block;
|
||||
opacity: 1;
|
||||
margin-block: 1em;
|
||||
margin-inline: 0;
|
||||
user-select: none;
|
||||
width: 100%;
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
.setting__searxng-url {
|
||||
margin-top: 10px;
|
||||
opacity: 0;
|
||||
transition: opacity 250ms ease-in-out;
|
||||
}
|
||||
label {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
color: #d8d8d8;
|
||||
opacity: .6;
|
||||
transition: opacity .4s ease-in-out;
|
||||
display: block;
|
||||
width: calc(100% - 48px) ;
|
||||
text-align: right;
|
||||
z-index: 100;
|
||||
user-select: none;
|
||||
text-align: start;
|
||||
margin-left: 20px;
|
||||
}
|
||||
input[type="radio"]{
|
||||
display: none;
|
||||
width: 0;
|
||||
}
|
||||
label:hover, input[type="radio"]:checked+label {
|
||||
opacity: 1;
|
||||
}
|
||||
.popup{
|
||||
width: 98%;
|
||||
height: 80%;
|
||||
margin: 0 auto;
|
||||
min-height: 400px;
|
||||
max-height: 400px;
|
||||
border-radius: 48px;
|
||||
box-sizing: border-box;
|
||||
background-color: var(--background-color);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-self: center;
|
||||
}
|
||||
.tabs{
|
||||
width: 100%;
|
||||
max-width: 240px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
position: relative;
|
||||
gap: 25px
|
||||
}
|
||||
.marker{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 200%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
top: calc(-100% );
|
||||
left: 0;
|
||||
transition: transform .2s ease-in-out;
|
||||
background-color: var(--accent-color);
|
||||
}
|
||||
.marker #bottom, .marker #top{
|
||||
background-color: var(--background-highlight);
|
||||
}
|
||||
.marker #top{
|
||||
height: calc(50%);
|
||||
margin-bottom: auto;
|
||||
border-radius: 0 0 32px 0;
|
||||
}
|
||||
.marker #bottom{
|
||||
height: calc(50% - 72px);
|
||||
border-radius: 0 32px 0 0;
|
||||
}
|
||||
#setting-tab-proxy:checked ~ .marker{transform: translateY(0%)}
|
||||
#setting-tab-customization:checked ~ .marker{transform: translateY(13.5%)}
|
||||
#setting-tab-cloaking:checked ~ .marker{transform: translateY(27%)}
|
||||
#setting-tab-credits:checked ~ .marker{transform: translateY(41%)}
|
||||
</style>
|
||||
.setting__searxng-url {
|
||||
margin-top: 10px;
|
||||
opacity: 0;
|
||||
transition: opacity 250ms ease-in-out;
|
||||
}
|
||||
label {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
color: #d8d8d8;
|
||||
opacity: 0.6;
|
||||
transition: opacity 0.4s ease-in-out;
|
||||
display: block;
|
||||
width: calc(100% - 48px);
|
||||
text-align: right;
|
||||
z-index: 100;
|
||||
user-select: none;
|
||||
text-align: start;
|
||||
margin-left: 20px;
|
||||
}
|
||||
input[type="radio"] {
|
||||
display: none;
|
||||
width: 0;
|
||||
}
|
||||
label:hover,
|
||||
input[type="radio"]:checked + label {
|
||||
opacity: 1;
|
||||
}
|
||||
.popup {
|
||||
width: 98%;
|
||||
height: 80%;
|
||||
margin: 0 auto;
|
||||
min-height: 400px;
|
||||
max-height: 400px;
|
||||
border-radius: 48px;
|
||||
box-sizing: border-box;
|
||||
background-color: var(--background-color);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-self: center;
|
||||
}
|
||||
.tabs {
|
||||
width: 100%;
|
||||
max-width: 240px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
position: relative;
|
||||
gap: 25px;
|
||||
}
|
||||
.marker {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 200%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
top: calc(-100%);
|
||||
left: 0;
|
||||
transition: transform 0.2s ease-in-out;
|
||||
background-color: var(--accent-color);
|
||||
}
|
||||
.marker #bottom,
|
||||
.marker #top {
|
||||
background-color: var(--background-highlight);
|
||||
}
|
||||
.marker #top {
|
||||
height: calc(50%);
|
||||
margin-bottom: auto;
|
||||
border-radius: 0 0 32px 0;
|
||||
}
|
||||
.marker #bottom {
|
||||
height: calc(50% - 72px);
|
||||
border-radius: 0 32px 0 0;
|
||||
}
|
||||
#setting-tab-proxy:checked ~ .marker {
|
||||
transform: translateY(0%);
|
||||
}
|
||||
#setting-tab-customization:checked ~ .marker {
|
||||
transform: translateY(13.5%);
|
||||
}
|
||||
#setting-tab-cloaking:checked ~ .marker {
|
||||
transform: translateY(27%);
|
||||
}
|
||||
#setting-tab-credits:checked ~ .marker {
|
||||
transform: translateY(41%);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -3,159 +3,190 @@ const { inputID } = Astro.props;
|
|||
---
|
||||
|
||||
<label class="switch">
|
||||
<input id={inputID} checked="" type="checkbox">
|
||||
<div class="slider">
|
||||
<div class="circle">
|
||||
<svg class="cross" xml:space="preserve" style="enable-background:new 0 0 512 512" viewBox="0 0 365.696 365.696" y="0" x="0" height="6" width="6" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<path data-original="#000000" fill="currentColor" d="M243.188 182.86 356.32 69.726c12.5-12.5 12.5-32.766 0-45.247L341.238 9.398c-12.504-12.503-32.77-12.503-45.25 0L182.86 122.528 69.727 9.374c-12.5-12.5-32.766-12.5-45.247 0L9.375 24.457c-12.5 12.504-12.5 32.77 0 45.25l113.152 113.152L9.398 295.99c-12.503 12.503-12.503 32.769 0 45.25L24.48 356.32c12.5 12.5 32.766 12.5 45.247 0l113.132-113.132L295.99 356.32c12.503 12.5 32.769 12.5 45.25 0l15.081-15.082c12.5-12.504 12.5-32.77 0-45.25zm0 0"></path>
|
||||
</g>
|
||||
</svg>
|
||||
<svg class="checkmark" xml:space="preserve" style="enable-background:new 0 0 512 512" viewBox="0 0 24 24" y="0" x="0" height="10" width="10" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<path class="" data-original="#000000" fill="currentColor" d="M9.707 19.121a.997.997 0 0 1-1.414 0l-5.646-5.647a1.5 1.5 0 0 1 0-2.121l.707-.707a1.5 1.5 0 0 1 2.121 0L9 14.171l9.525-9.525a1.5 1.5 0 0 1 2.121 0l.707.707a1.5 1.5 0 0 1 0 2.121z"></path>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<input id={inputID} checked="" type="checkbox" />
|
||||
<div class="slider">
|
||||
<div class="circle">
|
||||
<svg
|
||||
class="cross"
|
||||
xml:space="preserve"
|
||||
style="enable-background:new 0 0 512 512"
|
||||
viewBox="0 0 365.696 365.696"
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<path
|
||||
data-original="#000000"
|
||||
fill="currentColor"
|
||||
d="M243.188 182.86 356.32 69.726c12.5-12.5 12.5-32.766 0-45.247L341.238 9.398c-12.504-12.503-32.77-12.503-45.25 0L182.86 122.528 69.727 9.374c-12.5-12.5-32.766-12.5-45.247 0L9.375 24.457c-12.5 12.504-12.5 32.77 0 45.25l113.152 113.152L9.398 295.99c-12.503 12.503-12.503 32.769 0 45.25L24.48 356.32c12.5 12.5 32.766 12.5 45.247 0l113.132-113.132L295.99 356.32c12.503 12.5 32.769 12.5 45.25 0l15.081-15.082c12.5-12.504 12.5-32.77 0-45.25zm0 0"
|
||||
></path>
|
||||
</g>
|
||||
</svg>
|
||||
<svg
|
||||
class="checkmark"
|
||||
xml:space="preserve"
|
||||
style="enable-background:new 0 0 512 512"
|
||||
viewBox="0 0 24 24"
|
||||
y="0"
|
||||
x="0"
|
||||
height="10"
|
||||
width="10"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<path
|
||||
class=""
|
||||
data-original="#000000"
|
||||
fill="currentColor"
|
||||
d="M9.707 19.121a.997.997 0 0 1-1.414 0l-5.646-5.647a1.5 1.5 0 0 1 0-2.121l.707-.707a1.5 1.5 0 0 1 2.121 0L9 14.171l9.525-9.525a1.5 1.5 0 0 1 2.121 0l.707.707a1.5 1.5 0 0 1 0 2.121z"
|
||||
></path>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<style>
|
||||
.switch {
|
||||
--switch-width: 46px;
|
||||
--switch-height: 24px;
|
||||
--switch-bg: rgb(131, 131, 131);
|
||||
--switch-checked-bg: rgb(0, 218, 80);
|
||||
--switch-offset: calc((var(--switch-height) - var(--circle-diameter)) / 2);
|
||||
--switch-transition: all .2s cubic-bezier(0.27, 0.2, 0.25, 1.51);
|
||||
--circle-diameter: 18px;
|
||||
--circle-bg: #fff;
|
||||
--circle-shadow: 1px 1px 2px rgba(146, 146, 146, 0.45);
|
||||
--circle-checked-shadow: -1px 1px 2px rgba(163, 163, 163, 0.45);
|
||||
--circle-transition: var(--switch-transition);
|
||||
--icon-transition: all .2s cubic-bezier(0.27, 0.2, 0.25, 1.51);
|
||||
--icon-cross-color: var(--switch-bg);
|
||||
--icon-cross-size: 6px;
|
||||
--icon-checkmark-color: var(--switch-checked-bg);
|
||||
--icon-checkmark-size: 10px;
|
||||
--effect-width: calc(var(--circle-diameter) / 2);
|
||||
--effect-height: calc(var(--effect-width) / 2 - 1px);
|
||||
--effect-bg: var(--circle-bg);
|
||||
--effect-border-radius: 1px;
|
||||
--effect-transition: all .2s ease-in-out;
|
||||
}
|
||||
.switch {
|
||||
--switch-width: 46px;
|
||||
--switch-height: 24px;
|
||||
--switch-bg: rgb(131, 131, 131);
|
||||
--switch-checked-bg: rgb(0, 218, 80);
|
||||
--switch-offset: calc((var(--switch-height) - var(--circle-diameter)) / 2);
|
||||
--switch-transition: all 0.2s cubic-bezier(0.27, 0.2, 0.25, 1.51);
|
||||
--circle-diameter: 18px;
|
||||
--circle-bg: #fff;
|
||||
--circle-shadow: 1px 1px 2px rgba(146, 146, 146, 0.45);
|
||||
--circle-checked-shadow: -1px 1px 2px rgba(163, 163, 163, 0.45);
|
||||
--circle-transition: var(--switch-transition);
|
||||
--icon-transition: all 0.2s cubic-bezier(0.27, 0.2, 0.25, 1.51);
|
||||
--icon-cross-color: var(--switch-bg);
|
||||
--icon-cross-size: 6px;
|
||||
--icon-checkmark-color: var(--switch-checked-bg);
|
||||
--icon-checkmark-size: 10px;
|
||||
--effect-width: calc(var(--circle-diameter) / 2);
|
||||
--effect-height: calc(var(--effect-width) / 2 - 1px);
|
||||
--effect-bg: var(--circle-bg);
|
||||
--effect-border-radius: 1px;
|
||||
--effect-transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.switch input {
|
||||
display: none;
|
||||
}
|
||||
.switch input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.switch {
|
||||
display: inline-block;
|
||||
}
|
||||
.switch {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.switch svg {
|
||||
-webkit-transition: var(--icon-transition);
|
||||
-o-transition: var(--icon-transition);
|
||||
transition: var(--icon-transition);
|
||||
position: absolute;
|
||||
height: auto;
|
||||
}
|
||||
.switch svg {
|
||||
-webkit-transition: var(--icon-transition);
|
||||
-o-transition: var(--icon-transition);
|
||||
transition: var(--icon-transition);
|
||||
position: absolute;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.switch .checkmark {
|
||||
width: var(--icon-checkmark-size);
|
||||
color: var(--icon-checkmark-color);
|
||||
-webkit-transform: scale(0);
|
||||
-ms-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
.switch .checkmark {
|
||||
width: var(--icon-checkmark-size);
|
||||
color: var(--icon-checkmark-color);
|
||||
-webkit-transform: scale(0);
|
||||
-ms-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.switch .cross {
|
||||
width: var(--icon-cross-size);
|
||||
color: var(--icon-cross-color);
|
||||
}
|
||||
.switch .cross {
|
||||
width: var(--icon-cross-size);
|
||||
color: var(--icon-cross-color);
|
||||
}
|
||||
|
||||
.slider {
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
width: var(--switch-width);
|
||||
height: var(--switch-height);
|
||||
background: var(--switch-bg);
|
||||
border-radius: 999px;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
-webkit-transition: var(--switch-transition);
|
||||
-o-transition: var(--switch-transition);
|
||||
transition: var(--switch-transition);
|
||||
cursor: pointer;
|
||||
}
|
||||
.slider {
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
width: var(--switch-width);
|
||||
height: var(--switch-height);
|
||||
background: var(--switch-bg);
|
||||
border-radius: 999px;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
-webkit-transition: var(--switch-transition);
|
||||
-o-transition: var(--switch-transition);
|
||||
transition: var(--switch-transition);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.circle {
|
||||
width: var(--circle-diameter);
|
||||
height: var(--circle-diameter);
|
||||
background: var(--circle-bg);
|
||||
border-radius: inherit;
|
||||
-webkit-box-shadow: var(--circle-shadow);
|
||||
box-shadow: var(--circle-shadow);
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
-webkit-transition: var(--circle-transition);
|
||||
-o-transition: var(--circle-transition);
|
||||
transition: var(--circle-transition);
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
left: var(--switch-offset);
|
||||
}
|
||||
.circle {
|
||||
width: var(--circle-diameter);
|
||||
height: var(--circle-diameter);
|
||||
background: var(--circle-bg);
|
||||
border-radius: inherit;
|
||||
-webkit-box-shadow: var(--circle-shadow);
|
||||
box-shadow: var(--circle-shadow);
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
-webkit-transition: var(--circle-transition);
|
||||
-o-transition: var(--circle-transition);
|
||||
transition: var(--circle-transition);
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
left: var(--switch-offset);
|
||||
}
|
||||
|
||||
.slider::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: var(--effect-width);
|
||||
height: var(--effect-height);
|
||||
left: calc(var(--switch-offset) + (var(--effect-width) / 2));
|
||||
background: var(--effect-bg);
|
||||
border-radius: var(--effect-border-radius);
|
||||
-webkit-transition: var(--effect-transition);
|
||||
-o-transition: var(--effect-transition);
|
||||
transition: var(--effect-transition);
|
||||
}
|
||||
.slider::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: var(--effect-width);
|
||||
height: var(--effect-height);
|
||||
left: calc(var(--switch-offset) + (var(--effect-width) / 2));
|
||||
background: var(--effect-bg);
|
||||
border-radius: var(--effect-border-radius);
|
||||
-webkit-transition: var(--effect-transition);
|
||||
-o-transition: var(--effect-transition);
|
||||
transition: var(--effect-transition);
|
||||
}
|
||||
|
||||
/* actions */
|
||||
/* actions */
|
||||
|
||||
.switch input:checked+.slider {
|
||||
background: var(--switch-checked-bg);
|
||||
}
|
||||
.switch input:checked + .slider {
|
||||
background: var(--switch-checked-bg);
|
||||
}
|
||||
|
||||
.switch input:checked+.slider .checkmark {
|
||||
-webkit-transform: scale(1);
|
||||
-ms-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
.switch input:checked + .slider .checkmark {
|
||||
-webkit-transform: scale(1);
|
||||
-ms-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.switch input:checked+.slider .cross {
|
||||
-webkit-transform: scale(0);
|
||||
-ms-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
.switch input:checked + .slider .cross {
|
||||
-webkit-transform: scale(0);
|
||||
-ms-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.switch input:checked+.slider::before {
|
||||
left: calc(100% - var(--effect-width) - (var(--effect-width) / 2) - var(--switch-offset));
|
||||
}
|
||||
.switch input:checked + .slider::before {
|
||||
left: calc(100% - var(--effect-width) - (var(--effect-width) / 2) - var(--switch-offset));
|
||||
}
|
||||
|
||||
.switch input:checked+.slider .circle {
|
||||
left: calc(100% - var(--circle-diameter) - var(--switch-offset));
|
||||
-webkit-box-shadow: var(--circle-checked-shadow);
|
||||
box-shadow: var(--circle-checked-shadow);
|
||||
}
|
||||
</style>
|
||||
.switch input:checked + .slider .circle {
|
||||
left: calc(100% - var(--circle-diameter) - var(--switch-offset));
|
||||
-webkit-box-shadow: var(--circle-checked-shadow);
|
||||
box-shadow: var(--circle-checked-shadow);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
<script>
|
||||
function switchTheme() {
|
||||
let currentTheme = localStorage.getItem("alu__selectedTheme")
|
||||
function switchTheme() {
|
||||
let currentTheme = localStorage.getItem("alu__selectedTheme");
|
||||
|
||||
if (currentTheme) {
|
||||
document.documentElement.setAttribute("data-theme", JSON.parse(currentTheme).value.toLowerCase());
|
||||
let footer = document.getElementById('footer');
|
||||
if (footer) {
|
||||
footer.dataset.theme = JSON.parse(currentTheme).value.toLowerCase();
|
||||
}
|
||||
}
|
||||
if (currentTheme) {
|
||||
document.documentElement.setAttribute(
|
||||
"data-theme",
|
||||
JSON.parse(currentTheme).value.toLowerCase()
|
||||
);
|
||||
let footer = document.getElementById("footer");
|
||||
if (footer) {
|
||||
footer.dataset.theme = JSON.parse(currentTheme).value.toLowerCase();
|
||||
}
|
||||
}
|
||||
switchTheme()
|
||||
}
|
||||
switchTheme();
|
||||
|
||||
|
||||
|
||||
document.addEventListener('astro:after-swap', switchTheme)
|
||||
</script>
|
||||
document.addEventListener("astro:after-swap", switchTheme);
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,82 +0,0 @@
|
|||
<script src="/uv/uv.bundle.js" transition:persist is:inline></script>
|
||||
<script src="/uv.config.js" transition:persist is:inline></script>
|
||||
<script transition:persist defer>
|
||||
// This is a hack to make sure window.__uv$config is defined, because this means everything has been.
|
||||
if (window.__uv$config == undefined) window.location.reload();
|
||||
var form = document.querySelector('form');
|
||||
var input = document.querySelector('input');
|
||||
window.navigator.serviceWorker.register('/sw.js', {
|
||||
scope: window.__uv$config.prefix
|
||||
})
|
||||
|
||||
form.addEventListener('submit', (event) => {
|
||||
event.preventDefault();
|
||||
let loadingContent = document.getElementById('loading-content');
|
||||
loadingContent.style.opacity = 1;
|
||||
let url = input.value.trim();
|
||||
if (!isUrl(url)) url = getSearchEngine() + url;
|
||||
else if (!(url.startsWith('https://') || url.startsWith('http://'))) url = 'http://' + url;
|
||||
|
||||
let iframe = document.getElementById('proxy-frame');
|
||||
iframe.src = window.__uv$config.prefix + window.__uv$config.encodeUrl(url);
|
||||
iframe.style.pointerEvents = "auto";
|
||||
iframe.classList.add("proxy-frame");
|
||||
document.body.appendChild(iframe);
|
||||
iframe.addEventListener('load', () => {
|
||||
let topBar = document.getElementById('top-bar');
|
||||
loadingContent.style.opacity = 0;
|
||||
topBar.innerHTML = "";
|
||||
topBar.classList.add("top-bar");
|
||||
let closeButton = document.createElement('button');
|
||||
closeButton.classList.add("close-button")
|
||||
closeButton.innerText = "Close";
|
||||
closeButton.addEventListener('click', () => {
|
||||
iframe.style.opacity = 0;
|
||||
topBar.style.opacity = 0;
|
||||
iframe.style.pointerEvents = "none";
|
||||
topBar.style.pointerEvents = "none";
|
||||
});
|
||||
let urlText = document.createElement('p');
|
||||
urlText.classList.add("url-text");
|
||||
urlText.innerText = window.__uv$config.decodeUrl(iframe.src.split(__uv$config.prefix)[1]);
|
||||
iframe.style.opacity = 1;
|
||||
topBar.style.opacity = 1;
|
||||
topBar.style.pointerEvents = "auto";
|
||||
topBar.appendChild(closeButton);
|
||||
topBar.appendChild(urlText);
|
||||
document.body.appendChild(topBar);
|
||||
})
|
||||
});
|
||||
|
||||
function isUrl(val = ''){
|
||||
if (/^http(s?):\/\//.test(val) || val.includes('.') && val.substr(0, 1) !== ' ') return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
function getSearchEngine() {
|
||||
switch (JSON.parse(localStorage.getItem("alu__search_engine")).value.toLowerCase()) {
|
||||
case "google": {
|
||||
return "https://google.com/search?q=";
|
||||
}
|
||||
case "bing": {
|
||||
return "https://bing.com/search?q=d";
|
||||
}
|
||||
case "brave": {
|
||||
return "https://search.brave.com/search?q=";
|
||||
}
|
||||
case "searx": {
|
||||
let localStorageURL = localStorage.getItem("alu__searxngUrl");
|
||||
if (localStorageURL) {
|
||||
if (localStorageURL == "") return "https://searxng.site/search?q=";
|
||||
// Ugly hack to remove the trailing slash :)
|
||||
if (localStorageURL.endsWith("/")) localStorageURL = localStorageURL.slice(0, -1);
|
||||
return localStorageURL + "/search?q=";
|
||||
}
|
||||
else return "https://searxng.site/search?q=";
|
||||
}
|
||||
default: {
|
||||
return "https://google.com/search?q="
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
105
src/components/WaveSVG.astro
Normal file
105
src/components/WaveSVG.astro
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
<svg
|
||||
width="100%"
|
||||
height="100%"
|
||||
preserveAspectRatio="none"
|
||||
id="svg"
|
||||
viewBox="0 0 1440 390"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="transition duration-300 ease-in-out delay-150">
|
||||
<style>
|
||||
.path-0 {
|
||||
animation: pathAnim-0 15s;
|
||||
animation-timing-function: linear;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
@keyframes pathAnim-0 {
|
||||
0% {
|
||||
d: path(
|
||||
"M 0,400 L 0,100 C 124.53333333333336,122.66666666666667 249.06666666666672,145.33333333333334 415,143 C 580.9333333333333,140.66666666666666 788.2666666666667,113.33333333333333 966,102 C 1143.7333333333333,90.66666666666667 1291.8666666666668,95.33333333333334 1440,100 L 1440,400 L 0,400 Z"
|
||||
);
|
||||
}
|
||||
25% {
|
||||
d: path(
|
||||
"M 0,400 L 0,100 C 171.19999999999993,71.6 342.39999999999986,43.2 497,54 C 651.6000000000001,64.8 789.6000000000001,114.80000000000001 944,129 C 1098.3999999999999,143.2 1269.1999999999998,121.6 1440,100 L 1440,400 L 0,400 Z"
|
||||
);
|
||||
}
|
||||
50% {
|
||||
d: path(
|
||||
"M 0,400 L 0,100 C 186.66666666666669,82.13333333333333 373.33333333333337,64.26666666666667 540,54 C 706.6666666666666,43.733333333333334 853.3333333333333,41.06666666666666 1000,50 C 1146.6666666666667,58.93333333333334 1293.3333333333335,79.46666666666667 1440,100 L 1440,400 L 0,400 Z"
|
||||
);
|
||||
}
|
||||
75% {
|
||||
d: path(
|
||||
"M 0,400 L 0,100 C 110.13333333333333,74.53333333333333 220.26666666666665,49.06666666666666 393,58 C 565.7333333333333,66.93333333333334 801.0666666666666,110.26666666666668 986,123 C 1170.9333333333334,135.73333333333332 1305.4666666666667,117.86666666666666 1440,100 L 1440,400 L 0,400 Z"
|
||||
);
|
||||
}
|
||||
100% {
|
||||
d: path(
|
||||
"M 0,400 L 0,100 C 124.53333333333336,122.66666666666667 249.06666666666672,145.33333333333334 415,143 C 580.9333333333333,140.66666666666666 788.2666666666667,113.33333333333333 966,102 C 1143.7333333333333,90.66666666666667 1291.8666666666668,95.33333333333334 1440,100 L 1440,400 L 0,400 Z"
|
||||
);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style media="screen"></style>
|
||||
<defs>
|
||||
<linearGradient id="gradient" x1="0%" y1="53%" x2="100%" y2="47%">
|
||||
<stop offset="5%" stop-color="var(--accent-color)"></stop>
|
||||
<stop offset="95%" stop-color="var(--accent-color-brighter)"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path
|
||||
d="M 0,400 L 0,100 C 124.53333333333336,122.66666666666667 249.06666666666672,145.33333333333334 415,143 C 580.9333333333333,140.66666666666666 788.2666666666667,113.33333333333333 966,102 C 1143.7333333333333,90.66666666666667 1291.8666666666668,95.33333333333334 1440,100 L 1440,400 L 0,400 Z"
|
||||
stroke="none"
|
||||
stroke-width="0"
|
||||
fill="url(#gradient)"
|
||||
fill-opacity="0.53"
|
||||
class="transition-all duration-300 ease-in-out delay-150 path-0"></path>
|
||||
<style>
|
||||
.path-1 {
|
||||
animation: pathAnim-1 15s;
|
||||
animation-timing-function: linear;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
@keyframes pathAnim-1 {
|
||||
0% {
|
||||
d: path(
|
||||
"M 0,400 L 0,233 C 170.53333333333336,233.66666666666666 341.0666666666667,234.33333333333331 507,236 C 672.9333333333333,237.66666666666669 834.2666666666667,240.33333333333334 989,240 C 1143.7333333333333,239.66666666666666 1291.8666666666668,236.33333333333331 1440,233 L 1440,400 L 0,400 Z"
|
||||
);
|
||||
}
|
||||
25% {
|
||||
d: path(
|
||||
"M 0,400 L 0,233 C 202,220.46666666666667 404,207.93333333333334 539,220 C 674,232.06666666666666 742.0000000000001,268.7333333333333 881,275 C 1019.9999999999999,281.2666666666667 1230,257.1333333333333 1440,233 L 1440,400 L 0,400 Z"
|
||||
);
|
||||
}
|
||||
50% {
|
||||
d: path(
|
||||
"M 0,400 L 0,233 C 181.33333333333337,210.86666666666667 362.66666666666674,188.73333333333332 512,188 C 661.3333333333333,187.26666666666668 778.6666666666665,207.93333333333334 928,219 C 1077.3333333333335,230.06666666666666 1258.6666666666667,231.53333333333333 1440,233 L 1440,400 L 0,400 Z"
|
||||
);
|
||||
}
|
||||
75% {
|
||||
d: path(
|
||||
"M 0,400 L 0,233 C 195.06666666666666,222.86666666666667 390.1333333333333,212.73333333333332 559,216 C 727.8666666666667,219.26666666666668 870.5333333333333,235.93333333333334 1013,241 C 1155.4666666666667,246.06666666666666 1297.7333333333333,239.53333333333333 1440,233 L 1440,400 L 0,400 Z"
|
||||
);
|
||||
}
|
||||
100% {
|
||||
d: path(
|
||||
"M 0,400 L 0,233 C 170.53333333333336,233.66666666666666 341.0666666666667,234.33333333333331 507,236 C 672.9333333333333,237.66666666666669 834.2666666666667,240.33333333333334 989,240 C 1143.7333333333333,239.66666666666666 1291.8666666666668,236.33333333333331 1440,233 L 1440,400 L 0,400 Z"
|
||||
);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style media="screen"></style>
|
||||
<defs>
|
||||
<linearGradient id="gradient" x1="0%" y1="53%" x2="100%" y2="47%">
|
||||
<stop offset="5%" stop-color="#702dc2"></stop>
|
||||
<stop offset="95%" stop-color="#3d097d"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path
|
||||
d="M 0,400 L 0,233 C 170.53333333333336,233.66666666666666 341.0666666666667,234.33333333333331 507,236 C 672.9333333333333,237.66666666666669 834.2666666666667,240.33333333333334 989,240 C 1143.7333333333333,239.66666666666666 1291.8666666666668,236.33333333333331 1440,233 L 1440,400 L 0,400 Z"
|
||||
stroke="none"
|
||||
stroke-width="0"
|
||||
fill="url(#gradient)"
|
||||
fill-opacity="1"
|
||||
class="transition-all duration-300 ease-in-out delay-150 path-1"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.3 KiB |
|
|
@ -1,11 +1,40 @@
|
|||
<script is:inline>
|
||||
console.log("%cWelcome to Alu", "color: #0251d9; font-size: 2rem; font-weight: bold; text-shadow: 2px 2px 0 #033c9e;");
|
||||
<script>
|
||||
declare global {
|
||||
interface Navigator {
|
||||
deviceMemory: number;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("%cSystem Information: ", "color: #025bf5; font-size: 1rem; font-weight: bold;");
|
||||
console.log("%cOS: %c" + navigator.platform, "color: #025bf5; font-size: 0.75rem; font-weight: bold;", "color: #025bf5; font-size: 0.75rem;");
|
||||
console.log("%cBrowser: %c" + navigator.userAgent, "color: #025bf5; font-size: 0.75rem; font-weight: bold;", "color: #025bf5; font-size: 0.75rem;");
|
||||
console.log("%cCPU Cores: %c" + navigator.hardwareConcurrency, "color: #025bf5; font-size: 0.75rem; font-weight: bold;", "color: #025bf5; font-size: 0.75rem;");
|
||||
// Cmon firefox, do we really not support this?? Basic stuff here from the "indie browser".
|
||||
console.log("%cMemory: %c" + navigator.deviceMemory + "GB", "color: #025bf5; font-size: 0.75rem; font-weight: bold;", "color: #025bf5; font-size: 0.75rem;");
|
||||
console.log("%cPlease include this information in a bug report!", "color: #025bf5; font-size: 0.75rem; font-weight: bold;");
|
||||
</script>
|
||||
let primaryColor = "#8c25fa";
|
||||
let secondaryColor = "#601aab";
|
||||
console.log(
|
||||
"%cWelcome to Alu",
|
||||
`color: ${primaryColor}; font-size: 2rem; font-weight: bold; text-shadow: 2px 2px 0 ${secondaryColor};`
|
||||
);
|
||||
|
||||
console.log(
|
||||
"%cSystem Information: ",
|
||||
`color: ${primaryColor}; font-size: 1rem; font-weight: bold;`
|
||||
);
|
||||
console.log(
|
||||
"%cOS: " + navigator.platform,
|
||||
`color: ${primaryColor}; font-size: 0.75rem; font-weight: bold;`
|
||||
);
|
||||
console.log(
|
||||
"%cBrowser: " + navigator.userAgent,
|
||||
`color: ${primaryColor}; font-size: 0.75rem; font-weight: bold;`
|
||||
);
|
||||
console.log(
|
||||
"%cCPU Cores: " + navigator.hardwareConcurrency,
|
||||
`color: ${primaryColor}; font-size: 0.75rem; font-weight: bold;`
|
||||
);
|
||||
// Cmon firefox, do we really not support this?? Basic stuff here from the "indie browser".
|
||||
console.log(
|
||||
"%cMemory: " + navigator.deviceMemory + "GB",
|
||||
`color: ${primaryColor}; font-size: 0.75rem; font-weight: bold;`
|
||||
);
|
||||
console.log(
|
||||
"%cPlease include this information in a bug report!",
|
||||
`color: ${primaryColor}; font-size: 0.75rem; font-weight: bold;`
|
||||
);
|
||||
</script>
|
||||
|
|
|
|||
434
src/env.d.ts
vendored
434
src/env.d.ts
vendored
|
|
@ -1,205 +1,241 @@
|
|||
/// <reference types="astro/client" />
|
||||
|
||||
// ###> astro-i18n/type-generation ###
|
||||
type PrimaryLocale = "en"
|
||||
type SecondaryLocale = ""
|
||||
type Locale = PrimaryLocale | SecondaryLocale
|
||||
type RouteParameters = {"/games":undefined;"/":undefined;"/settings":undefined;"/404":undefined;}
|
||||
type Route = keyof RouteParameters
|
||||
type TranslationVariables = {"nav.brand":object|undefined;"nav.games":object|undefined;"nav.settings":object|undefined;}
|
||||
type Translation = keyof TranslationVariables
|
||||
type Environment = "none"|"node"|"browser"
|
||||
type PrimaryLocale = "en";
|
||||
type SecondaryLocale = "";
|
||||
type Locale = PrimaryLocale | SecondaryLocale;
|
||||
type RouteParameters = {
|
||||
"/games": undefined;
|
||||
"/": undefined;
|
||||
"/settings": undefined;
|
||||
"/404": undefined;
|
||||
};
|
||||
type Route = keyof RouteParameters;
|
||||
type TranslationVariables = {
|
||||
"nav.brand": object | undefined;
|
||||
"nav.games": object | undefined;
|
||||
"nav.settings": object | undefined;
|
||||
};
|
||||
type Translation = keyof TranslationVariables;
|
||||
type Environment = "none" | "node" | "browser";
|
||||
declare module "astro-i18n" {
|
||||
type GetStaticPathsProps = {paginate:Function;rss:Function}
|
||||
type GetStaticPathsItem = {params:Record<string,number|string|undefined>;props?:Record<string,unknown>}
|
||||
type DeepStringRecord = {[key: string]:string|DeepStringRecord}
|
||||
type TranslationDirectory = {i18n?:string;pages?: string}
|
||||
export type Translations = {[group: string]:{[locale: string]: DeepStringRecord}}
|
||||
export type TranslationFormatters = {[formatterName: string]:(value:unknown,...args:unknown[])=>unknown}
|
||||
export type TranslationLoadingRules = {groups:string[];routes: string[]}[]
|
||||
export type SegmentTranslations = {[secondaryLocale: string]:{[segment: string]:string}}
|
||||
export interface AstroI18nConfig {primaryLocale:string;secondaryLocales:string[];fallbackLocale:string;showPrimaryLocale:boolean;trailingSlash:"always"|"never";run:"server"|"client+server";translations:Translations;translationLoadingRules:TranslationLoadingRules;translationDirectory:TranslationDirectory;routes:SegmentTranslations;srcDir:string;}
|
||||
/** Typed astro-i18n config definition. */
|
||||
export function defineAstroI18nConfig(config: Partial<AstroI18nConfig>): Partial<AstroI18nConfig>
|
||||
/** The `astro-i18n` middleware. */
|
||||
export function useAstroI18n(
|
||||
config?: Partial<AstroI18nConfig> | string,
|
||||
formatters?: TranslationFormatters,
|
||||
): (...args: any[]) => any
|
||||
/** Workaround function to make astroI18n work inside getStaticPaths. This is because Astro's getStaticPaths runs before everything which doesn't allows astroI18n to update its state automatically. */
|
||||
function createGetStaticPaths(
|
||||
callback: (
|
||||
props: GetStaticPathsProps,
|
||||
) => GetStaticPathsItem[] | Promise<GetStaticPathsItem[]>,
|
||||
): (props: GetStaticPathsProps & {
|
||||
astroI18n?: {
|
||||
locale: string;
|
||||
};
|
||||
}) => Promise<GetStaticPathsItem[]>
|
||||
/**
|
||||
* @param key The translation key, for example `"my.nested.translation.key"`.
|
||||
* @param properties An object containing your interpolation variables and/or your variants, for example `{ variant: 3, interpolation: "text" }`.
|
||||
* @param options `route`: Overrides the current route, you will be able to access that route's translations. `locale`: Overrides the current locale, this allows you to control which language you want to translate to. `fallbackLocale`: Overrides the fallback locale.
|
||||
*/
|
||||
export function t<T extends Translation>(
|
||||
key: T | string & {},
|
||||
...args: undefined extends TranslationVariables[T]
|
||||
? [
|
||||
properties?: keyof TranslationVariables extends T
|
||||
? Record<string, unknown>
|
||||
: TranslationVariables[T],
|
||||
options?: {
|
||||
route?: Route | string & {}
|
||||
locale?: Locale | string & {}
|
||||
fallbackLocale?: Locale | string & {}
|
||||
}
|
||||
]
|
||||
: [
|
||||
properties: TranslationVariables[T],
|
||||
options?: {
|
||||
route?: Route | string & {}
|
||||
locale?: Locale | string & {}
|
||||
fallbackLocale?: Locale | string & {}
|
||||
}
|
||||
]
|
||||
): string
|
||||
/**
|
||||
* @param route A route in any of the configured languages, for example `"/en/my/english/route/[param]"`.
|
||||
* @param parameters An object containing your route parameters, for example `{ slug: "my-blog-post-slug" }`.
|
||||
* @param options `targetLocale`: Overrides the target locale. `routeLocale`: Overrides the given route locale, this is useful if astro-i18n cannot figure out the route's locale. `showPrimaryLocale`: Overrides the showPrimaryLocale parameter. `query`: Adds these query parameters at the end of the translated route.
|
||||
*/
|
||||
export function l<T extends Route>(
|
||||
route: T | string & {},
|
||||
...args: T extends keyof RouteParameters
|
||||
? undefined extends RouteParameters[T]
|
||||
? [
|
||||
parameters?: Record<string, string>,
|
||||
options?: {
|
||||
targetLocale?: string,
|
||||
routeLocale?: string,
|
||||
showPrimaryLocale?: string,
|
||||
query?: Record<string, unknown>
|
||||
}
|
||||
]
|
||||
: [
|
||||
parameters: RouteParameters[T],
|
||||
options?: {
|
||||
targetLocale?: string,
|
||||
routeLocale?: string,
|
||||
showPrimaryLocale?: string,
|
||||
query?: Record<string, unknown>
|
||||
}
|
||||
]
|
||||
: [
|
||||
parameters?: Record<string, string>,
|
||||
options?: {
|
||||
targetLocale?: string,
|
||||
routeLocale?: string,
|
||||
showPrimaryLocale?: string,
|
||||
query?: Record<string, unknown>
|
||||
}
|
||||
]
|
||||
): string
|
||||
class AstroI18n {
|
||||
/** The detected runtime environment. */
|
||||
environment: Environment
|
||||
/** The current page route. */
|
||||
route: string
|
||||
/** All page routes. For example: `["/", "/about", "/posts/[slug]"]` */
|
||||
pages: string[]
|
||||
/** The equivalent page for the current route. For example if route is equal to `"/posts/my-cool-cat"` this could return `"/posts/[slug]"`. */
|
||||
page: string
|
||||
/** The current page locale. */
|
||||
locale: Locale
|
||||
/** All configured locales. */
|
||||
locales: Locale[]
|
||||
/** The default/primary locale. */
|
||||
primaryLocale: PrimaryLocale
|
||||
/** Locales other than the default/primary one. */
|
||||
secondaryLocales: SecondaryLocale[]
|
||||
/** The fallback locale, when a translation is missing in a locale the fallback locale will be used to find a replacement. */
|
||||
fallbackLocale: Locale
|
||||
/** True when astro-i18n is initialized. */
|
||||
isInitialized: boolean
|
||||
/**
|
||||
* @param key The translation key, for example `"my.nested.translation.key"`.
|
||||
* @param properties An object containing your interpolation variables and/or your variants, for example `{ variant: 3, interpolation: "text" }`.
|
||||
* @param options `route`: Overrides the current route, you will be able to access that route's translations. `locale`: Overrides the current locale, this allows you to control which language you want to translate to. `fallbackLocale`: Overrides the fallback locale.
|
||||
*/
|
||||
t<T extends Translation>(
|
||||
key: T | string & {},
|
||||
...args: undefined extends TranslationVariables[T]
|
||||
? [
|
||||
properties?: keyof TranslationVariables extends T
|
||||
? Record<string, unknown>
|
||||
: TranslationVariables[T],
|
||||
options?: {
|
||||
route?: Route | string & {}
|
||||
locale?: Locale | string & {}
|
||||
fallbackLocale?: Locale | string & {}
|
||||
}
|
||||
]
|
||||
: [
|
||||
properties: TranslationVariables[T],
|
||||
options?: {
|
||||
route?: Route | string & {}
|
||||
locale?: Locale | string & {}
|
||||
fallbackLocale?: Locale | string & {}
|
||||
}
|
||||
]
|
||||
): string
|
||||
/**
|
||||
* @param route A route in any of the configured languages, for example `"/en/my/english/route/[param]"`.
|
||||
* @param parameters An object containing your route parameters, for example `{ slug: "my-blog-post-slug" }`.
|
||||
* @param options `targetLocale`: Overrides the target locale. `routeLocale`: Overrides the given route locale, this is useful if astro-i18n cannot figure out the route's locale. `showPrimaryLocale`: Overrides the showPrimaryLocale parameter. `query`: Adds these query parameters at the end of the translated route.
|
||||
*/
|
||||
l<T extends Route>(
|
||||
route: T | string & {},
|
||||
...args: T extends keyof RouteParameters
|
||||
? undefined extends RouteParameters[T]
|
||||
? [
|
||||
parameters?: Record<string, string>,
|
||||
options?: {
|
||||
targetLocale?: string,
|
||||
routeLocale?: string,
|
||||
showPrimaryLocale?: string,
|
||||
query?: Record<string, unknown>
|
||||
}
|
||||
]
|
||||
: [
|
||||
parameters: RouteParameters[T],
|
||||
options?: {
|
||||
targetLocale?: string,
|
||||
routeLocale?: string,
|
||||
showPrimaryLocale?: string,
|
||||
query?: Record<string, unknown>
|
||||
}
|
||||
]
|
||||
: [
|
||||
parameters?: Record<string, string>,
|
||||
options?: {
|
||||
targetLocale?: string,
|
||||
routeLocale?: string,
|
||||
showPrimaryLocale?: string,
|
||||
query?: Record<string, unknown>
|
||||
}
|
||||
]
|
||||
): string
|
||||
/** Adds new translations at runtime. */
|
||||
addTranslations(translations: Translations): this
|
||||
/** Adds new translation formatters at runtime. */
|
||||
addFormatters(translationFormatters: TranslationFormatters): this
|
||||
/** Adds new translation loading rules at runtime. */
|
||||
addTranslationLoadingRules(translationLoadingRules: TranslationLoadingRules): this
|
||||
/** Adds new route segment translations at runtime. */
|
||||
addRoutes(routes: SegmentTranslations): this
|
||||
/** Tries to parse one of the configured locales out of the given route. If no configured locale is found it will return `null`. */
|
||||
extractRouteLocale(route: string): string|null
|
||||
/** Initializes astro-i18n on the server-side. */
|
||||
initialize(config?: Partial<AstroI18nConfig> | string, formatters?: TranslationFormatters = {}): Promise<void>
|
||||
/** Redirects the user to the given destination. */
|
||||
redirect(destination: string | URL, status = 301)
|
||||
}
|
||||
export const astroI18n: AstroI18n
|
||||
type GetStaticPathsProps = { paginate: Function; rss: Function };
|
||||
type GetStaticPathsItem = {
|
||||
params: Record<string, number | string | undefined>;
|
||||
props?: Record<string, unknown>;
|
||||
};
|
||||
type DeepStringRecord = { [key: string]: string | DeepStringRecord };
|
||||
type TranslationDirectory = { i18n?: string; pages?: string };
|
||||
export type Translations = {
|
||||
[group: string]: { [locale: string]: DeepStringRecord };
|
||||
};
|
||||
export type TranslationFormatters = {
|
||||
[formatterName: string]: (value: unknown, ...args: unknown[]) => unknown;
|
||||
};
|
||||
export type TranslationLoadingRules = {
|
||||
groups: string[];
|
||||
routes: string[];
|
||||
}[];
|
||||
export type SegmentTranslations = {
|
||||
[secondaryLocale: string]: { [segment: string]: string };
|
||||
};
|
||||
export interface AstroI18nConfig {
|
||||
primaryLocale: string;
|
||||
secondaryLocales: string[];
|
||||
fallbackLocale: string;
|
||||
showPrimaryLocale: boolean;
|
||||
trailingSlash: "always" | "never";
|
||||
run: "server" | "client+server";
|
||||
translations: Translations;
|
||||
translationLoadingRules: TranslationLoadingRules;
|
||||
translationDirectory: TranslationDirectory;
|
||||
routes: SegmentTranslations;
|
||||
srcDir: string;
|
||||
}
|
||||
/** Typed astro-i18n config definition. */
|
||||
export function defineAstroI18nConfig(config: Partial<AstroI18nConfig>): Partial<AstroI18nConfig>;
|
||||
/** The `astro-i18n` middleware. */
|
||||
export function useAstroI18n(
|
||||
config?: Partial<AstroI18nConfig> | string,
|
||||
formatters?: TranslationFormatters
|
||||
): (...args: any[]) => any;
|
||||
/** Workaround function to make astroI18n work inside getStaticPaths. This is because Astro's getStaticPaths runs before everything which doesn't allows astroI18n to update its state automatically. */
|
||||
function createGetStaticPaths(
|
||||
callback: (props: GetStaticPathsProps) => GetStaticPathsItem[] | Promise<GetStaticPathsItem[]>
|
||||
): (
|
||||
props: GetStaticPathsProps & {
|
||||
astroI18n?: {
|
||||
locale: string;
|
||||
};
|
||||
}
|
||||
) => Promise<GetStaticPathsItem[]>;
|
||||
/**
|
||||
* @param key The translation key, for example `"my.nested.translation.key"`.
|
||||
* @param properties An object containing your interpolation variables and/or your variants, for example `{ variant: 3, interpolation: "text" }`.
|
||||
* @param options `route`: Overrides the current route, you will be able to access that route's translations. `locale`: Overrides the current locale, this allows you to control which language you want to translate to. `fallbackLocale`: Overrides the fallback locale.
|
||||
*/
|
||||
export function t<T extends Translation>(
|
||||
key: T | (string & {}),
|
||||
...args: undefined extends TranslationVariables[T]
|
||||
? [
|
||||
properties?: keyof TranslationVariables extends T
|
||||
? Record<string, unknown>
|
||||
: TranslationVariables[T],
|
||||
options?: {
|
||||
route?: Route | (string & {});
|
||||
locale?: Locale | (string & {});
|
||||
fallbackLocale?: Locale | (string & {});
|
||||
},
|
||||
]
|
||||
: [
|
||||
properties: TranslationVariables[T],
|
||||
options?: {
|
||||
route?: Route | (string & {});
|
||||
locale?: Locale | (string & {});
|
||||
fallbackLocale?: Locale | (string & {});
|
||||
},
|
||||
]
|
||||
): string;
|
||||
/**
|
||||
* @param route A route in any of the configured languages, for example `"/en/my/english/route/[param]"`.
|
||||
* @param parameters An object containing your route parameters, for example `{ slug: "my-blog-post-slug" }`.
|
||||
* @param options `targetLocale`: Overrides the target locale. `routeLocale`: Overrides the given route locale, this is useful if astro-i18n cannot figure out the route's locale. `showPrimaryLocale`: Overrides the showPrimaryLocale parameter. `query`: Adds these query parameters at the end of the translated route.
|
||||
*/
|
||||
export function l<T extends Route>(
|
||||
route: T | (string & {}),
|
||||
...args: T extends keyof RouteParameters
|
||||
? undefined extends RouteParameters[T]
|
||||
? [
|
||||
parameters?: Record<string, string>,
|
||||
options?: {
|
||||
targetLocale?: string;
|
||||
routeLocale?: string;
|
||||
showPrimaryLocale?: string;
|
||||
query?: Record<string, unknown>;
|
||||
},
|
||||
]
|
||||
: [
|
||||
parameters: RouteParameters[T],
|
||||
options?: {
|
||||
targetLocale?: string;
|
||||
routeLocale?: string;
|
||||
showPrimaryLocale?: string;
|
||||
query?: Record<string, unknown>;
|
||||
},
|
||||
]
|
||||
: [
|
||||
parameters?: Record<string, string>,
|
||||
options?: {
|
||||
targetLocale?: string;
|
||||
routeLocale?: string;
|
||||
showPrimaryLocale?: string;
|
||||
query?: Record<string, unknown>;
|
||||
},
|
||||
]
|
||||
): string;
|
||||
class AstroI18n {
|
||||
/** The detected runtime environment. */
|
||||
environment: Environment;
|
||||
/** The current page route. */
|
||||
route: string;
|
||||
/** All page routes. For example: `["/", "/about", "/posts/[slug]"]` */
|
||||
pages: string[];
|
||||
/** The equivalent page for the current route. For example if route is equal to `"/posts/my-cool-cat"` this could return `"/posts/[slug]"`. */
|
||||
page: string;
|
||||
/** The current page locale. */
|
||||
locale: Locale;
|
||||
/** All configured locales. */
|
||||
locales: Locale[];
|
||||
/** The default/primary locale. */
|
||||
primaryLocale: PrimaryLocale;
|
||||
/** Locales other than the default/primary one. */
|
||||
secondaryLocales: SecondaryLocale[];
|
||||
/** The fallback locale, when a translation is missing in a locale the fallback locale will be used to find a replacement. */
|
||||
fallbackLocale: Locale;
|
||||
/** True when astro-i18n is initialized. */
|
||||
isInitialized: boolean;
|
||||
/**
|
||||
* @param key The translation key, for example `"my.nested.translation.key"`.
|
||||
* @param properties An object containing your interpolation variables and/or your variants, for example `{ variant: 3, interpolation: "text" }`.
|
||||
* @param options `route`: Overrides the current route, you will be able to access that route's translations. `locale`: Overrides the current locale, this allows you to control which language you want to translate to. `fallbackLocale`: Overrides the fallback locale.
|
||||
*/
|
||||
t<T extends Translation>(
|
||||
key: T | (string & {}),
|
||||
...args: undefined extends TranslationVariables[T]
|
||||
? [
|
||||
properties?: keyof TranslationVariables extends T
|
||||
? Record<string, unknown>
|
||||
: TranslationVariables[T],
|
||||
options?: {
|
||||
route?: Route | (string & {});
|
||||
locale?: Locale | (string & {});
|
||||
fallbackLocale?: Locale | (string & {});
|
||||
},
|
||||
]
|
||||
: [
|
||||
properties: TranslationVariables[T],
|
||||
options?: {
|
||||
route?: Route | (string & {});
|
||||
locale?: Locale | (string & {});
|
||||
fallbackLocale?: Locale | (string & {});
|
||||
},
|
||||
]
|
||||
): string;
|
||||
/**
|
||||
* @param route A route in any of the configured languages, for example `"/en/my/english/route/[param]"`.
|
||||
* @param parameters An object containing your route parameters, for example `{ slug: "my-blog-post-slug" }`.
|
||||
* @param options `targetLocale`: Overrides the target locale. `routeLocale`: Overrides the given route locale, this is useful if astro-i18n cannot figure out the route's locale. `showPrimaryLocale`: Overrides the showPrimaryLocale parameter. `query`: Adds these query parameters at the end of the translated route.
|
||||
*/
|
||||
l<T extends Route>(
|
||||
route: T | (string & {}),
|
||||
...args: T extends keyof RouteParameters
|
||||
? undefined extends RouteParameters[T]
|
||||
? [
|
||||
parameters?: Record<string, string>,
|
||||
options?: {
|
||||
targetLocale?: string;
|
||||
routeLocale?: string;
|
||||
showPrimaryLocale?: string;
|
||||
query?: Record<string, unknown>;
|
||||
},
|
||||
]
|
||||
: [
|
||||
parameters: RouteParameters[T],
|
||||
options?: {
|
||||
targetLocale?: string;
|
||||
routeLocale?: string;
|
||||
showPrimaryLocale?: string;
|
||||
query?: Record<string, unknown>;
|
||||
},
|
||||
]
|
||||
: [
|
||||
parameters?: Record<string, string>,
|
||||
options?: {
|
||||
targetLocale?: string;
|
||||
routeLocale?: string;
|
||||
showPrimaryLocale?: string;
|
||||
query?: Record<string, unknown>;
|
||||
},
|
||||
]
|
||||
): string;
|
||||
/** Adds new translations at runtime. */
|
||||
addTranslations(translations: Translations): this;
|
||||
/** Adds new translation formatters at runtime. */
|
||||
addFormatters(translationFormatters: TranslationFormatters): this;
|
||||
/** Adds new translation loading rules at runtime. */
|
||||
addTranslationLoadingRules(translationLoadingRules: TranslationLoadingRules): this;
|
||||
/** Adds new route segment translations at runtime. */
|
||||
addRoutes(routes: SegmentTranslations): this;
|
||||
/** Tries to parse one of the configured locales out of the given route. If no configured locale is found it will return `null`. */
|
||||
extractRouteLocale(route: string): string | null;
|
||||
/** Initializes astro-i18n on the server-side. */
|
||||
initialize(
|
||||
config?: Partial<AstroI18nConfig> | string,
|
||||
formatters?: TranslationFormatters = {}
|
||||
): Promise<void>;
|
||||
/** Redirects the user to the given destination. */
|
||||
redirect(destination: string | URL, status = 301);
|
||||
}
|
||||
export const astroI18n: AstroI18n;
|
||||
}
|
||||
// ###< astro-i18n/type-generation ###
|
||||
|
|
|
|||
|
|
@ -1,48 +1,48 @@
|
|||
{
|
||||
"ultraviolet": "Ultraviolet",
|
||||
"ultraviolet": "Ultraviolet",
|
||||
|
||||
"pages.home": "Home | Alu",
|
||||
"pages.games": "Games | Alu",
|
||||
"pages.settings": "Settings | Alu",
|
||||
"pages.home": "Home | Alu",
|
||||
"pages.games": "Games | Alu",
|
||||
"pages.settings": "Settings | Alu",
|
||||
|
||||
"nav.brand": "Alu",
|
||||
"nav.games": "Games",
|
||||
"nav.settings": "Settings",
|
||||
|
||||
"nav.brand": "Alu",
|
||||
"nav.games": "Games",
|
||||
"nav.settings": "Settings",
|
||||
"menu.welcome": "Welcome to Alu",
|
||||
"menu.search": "Search...",
|
||||
|
||||
"menu.welcome": "Welcome to Alu",
|
||||
"menu.search": "Search...",
|
||||
"footer.brand": "Alu",
|
||||
"footer.madeWithLove": "Made with ❤️ by wearr",
|
||||
"footer.poweredBy": "Powered by Ultraviolet",
|
||||
"footer.services": "Services",
|
||||
"footer.socials": "Socials",
|
||||
"footer.aluProject": "Alu Project",
|
||||
|
||||
"footer.brand": "Alu",
|
||||
"footer.madeWithLove": "Made with ❤️ by wearr",
|
||||
"footer.services": "Services",
|
||||
"footer.socials": "Socials",
|
||||
"footer.aluProject": "Alu Project",
|
||||
"games.title": "Games",
|
||||
|
||||
"games.title": "Games",
|
||||
"settings.title": "Settings",
|
||||
"settings.proxy": "Proxy",
|
||||
"settings.proxy.auto": "Auto",
|
||||
"settings.proxy.selectedProxy": "Selected Proxy",
|
||||
"settings.proxy.searchEngine": "Search Engine",
|
||||
"settings.proxy.openPageWith": "Open With",
|
||||
"settings.proxy.openPageWith.embed": "Embed",
|
||||
"settings.proxy.openPageWith.newTab": "New Tab",
|
||||
"settings.proxy.searxngURL": "Searx URL",
|
||||
"settings.proxy.bareURL": "Bare URL",
|
||||
|
||||
"settings.title": "Settings",
|
||||
"settings.proxy": "Proxy",
|
||||
"settings.proxy.auto": "Auto",
|
||||
"settings.proxy.selectedProxy": "Selected Proxy",
|
||||
"settings.proxy.searchEngine": "Search Engine",
|
||||
"settings.proxy.openPageWith": "Open With",
|
||||
"settings.proxy.openPageWith.embed": "Embed",
|
||||
"settings.proxy.openPageWith.newTab": "New Tab",
|
||||
"settings.proxy.searxngURL": "Searx URL",
|
||||
"settings.proxy.bareURL": "Bare URL",
|
||||
"settings.customization": "Customization",
|
||||
"settings.customization.theme": "Theme",
|
||||
"settings.customization.theme.Alu": "Alu",
|
||||
"settings.customization.theme.Macchiato": "Macchiato",
|
||||
"settings.customization.theme.Mocha": "Mocha",
|
||||
"settings.customization.language": "Language",
|
||||
|
||||
"settings.customization": "Customization",
|
||||
"settings.customization.theme": "Theme",
|
||||
"settings.customization.theme.Alu": "Alu",
|
||||
"settings.customization.theme.Macchiato": "Macchiato",
|
||||
"settings.customization.theme.Mocha": "Mocha",
|
||||
"settings.customization.language": "Language",
|
||||
"settings.cloaking": "Cloaking",
|
||||
"settings.cloaking.subtext": "Change how your tab looks...",
|
||||
|
||||
"settings.cloaking": "Cloaking",
|
||||
"settings.cloaking.subtext": "Change how your tab looks...",
|
||||
|
||||
"settings.credits": "Credits",
|
||||
"settings.credits.mochaandmacchiatothemes": "Mocha & Macchiato Themes",
|
||||
"settings.credits.japaneseTranslations": "Japanese Translations"
|
||||
}
|
||||
"settings.credits": "Credits",
|
||||
"settings.credits.mochaandmacchiatothemes": "Mocha & Macchiato Themes",
|
||||
"settings.credits.japaneseTranslations": "Japanese Translations"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,46 +1,47 @@
|
|||
{
|
||||
"ultraviolet": "ウルトラバイオレット",
|
||||
|
||||
"pages.home": "ホーム | アルー",
|
||||
"pages.games": "ゲーム | アルー",
|
||||
"pages.settings": "設定 | アルー",
|
||||
"ultraviolet": "ウルトラバイオレット",
|
||||
|
||||
"nav.brand": "アルー",
|
||||
"nav.games": "ゲーム",
|
||||
"nav.settings": "設定",
|
||||
"pages.home": "ホーム | アルー",
|
||||
"pages.games": "ゲーム | アルー",
|
||||
"pages.settings": "設定 | アルー",
|
||||
|
||||
"menu.welcome": "アルーにようこそ",
|
||||
"menu.search": "検索...",
|
||||
"nav.brand": "アルー",
|
||||
"nav.games": "ゲーム",
|
||||
"nav.settings": "設定",
|
||||
|
||||
"footer.brand": "アルー",
|
||||
"footer.madeWithLove": "wearrによる❤️で作られました",
|
||||
"footer.services": "サービス",
|
||||
"footer.socials": "ソーシャル",
|
||||
"footer.aluProject": "アループロジェクト",
|
||||
"menu.welcome": "アルーにようこそ",
|
||||
"menu.search": "検索...",
|
||||
|
||||
"games.title": "ゲーム",
|
||||
"footer.brand": "アルー",
|
||||
"footer.madeWithLove": "wearrによる❤️で作られました",
|
||||
"footer.poweredBy": "「ウルトラバイオレット」による駆動",
|
||||
"footer.services": "サービス",
|
||||
"footer.socials": "ソーシャル",
|
||||
"footer.aluProject": "アループロジェクト",
|
||||
|
||||
"settings.title": "設定",
|
||||
"settings.proxy": "プロキシ",
|
||||
"settings.proxy.selectedProxy": "選択されたプロキシ",
|
||||
"settings.proxy.searchEngine": "検索エンジン",
|
||||
"settings.proxy.openPageWith": "開く",
|
||||
"settings.proxy.searxngURL": "SearxのURL",
|
||||
"settings.proxy.openPageWith.embed": "埋め込み",
|
||||
"settings.proxy.openPageWith.newTab": "新しいタブ",
|
||||
"settings.proxy.bareURL": "BareのURL",
|
||||
"games.title": "ゲーム",
|
||||
|
||||
"settings.customization": "カスタマイズ",
|
||||
"settings.customization.theme": "テーマ",
|
||||
"settings.customization.theme.Alu": "アルー",
|
||||
"settings.customization.theme.Macchiato": "マキアート",
|
||||
"settings.customization.theme.Mocha": "モカ",
|
||||
"settings.customization.language": "言語",
|
||||
|
||||
"settings.cloaking": "クローキング",
|
||||
"settings.cloaking.subtext": "タブの外観を変更します...",
|
||||
"settings.title": "設定",
|
||||
"settings.proxy": "プロキシ",
|
||||
"settings.proxy.selectedProxy": "選択されたプロキシ",
|
||||
"settings.proxy.searchEngine": "検索エンジン",
|
||||
"settings.proxy.openPageWith": "開く",
|
||||
"settings.proxy.searxngURL": "SearxのURL",
|
||||
"settings.proxy.openPageWith.embed": "埋め込み",
|
||||
"settings.proxy.openPageWith.newTab": "新しいタブ",
|
||||
"settings.proxy.bareURL": "BareのURL",
|
||||
|
||||
"settings.credits": "クレジット",
|
||||
"settings.credits.mochaandmacchiatothemes": "モカとマキアートテーマ",
|
||||
"settings.credits.japaneseTranslations": "日本語翻訳"
|
||||
}
|
||||
"settings.customization": "カスタマイズ",
|
||||
"settings.customization.theme": "テーマ",
|
||||
"settings.customization.theme.Alu": "アルー",
|
||||
"settings.customization.theme.Macchiato": "マキアート",
|
||||
"settings.customization.theme.Mocha": "モカ",
|
||||
"settings.customization.language": "言語",
|
||||
|
||||
"settings.cloaking": "クローキング",
|
||||
"settings.cloaking.subtext": "タブの外観を変更します...",
|
||||
|
||||
"settings.credits": "クレジット",
|
||||
"settings.credits.mochaandmacchiatothemes": "モカとマキアートテーマ",
|
||||
"settings.credits.japaneseTranslations": "日本語翻訳"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import en from './en.json';
|
||||
import jp from './jp.json';
|
||||
import en from "./en.json";
|
||||
import jp from "./jp.json";
|
||||
|
||||
export const defaultLang = "en";
|
||||
|
||||
export const defaultLang = 'en';
|
||||
|
||||
export const ui = {
|
||||
en,
|
||||
jp
|
||||
};
|
||||
en,
|
||||
jp,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { ui, defaultLang } from './ui';
|
||||
import { ui, defaultLang } from "./ui";
|
||||
|
||||
export function getLangFromUrl(url: URL) {
|
||||
// comma lol
|
||||
const [, lang] = url.pathname.split('/');
|
||||
const [, lang] = url.pathname.split("/");
|
||||
if (lang in ui) return lang as keyof typeof ui;
|
||||
return defaultLang;
|
||||
}
|
||||
|
||||
export function useTranslations(lang: keyof typeof ui) {
|
||||
return function t(key: keyof typeof ui[typeof defaultLang]) {
|
||||
return function t(key: keyof (typeof ui)[typeof defaultLang]) {
|
||||
return ui[lang][key] || ui[defaultLang][key];
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
262
src/json/games.json
Normal file
262
src/json/games.json
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
{
|
||||
"1v1.lol": {
|
||||
"name": "1v1.lol",
|
||||
"image": "/games/1v1.lol/logo.png",
|
||||
"slug": "1v1.lol"
|
||||
},
|
||||
"2048": {
|
||||
"name": "2048",
|
||||
"image": "/games/2048/logo.png",
|
||||
"slug": "2048"
|
||||
},
|
||||
"backrooms": {
|
||||
"name": "The Backrooms",
|
||||
"image": "/games/backrooms/logo.png",
|
||||
"slug": "backrooms"
|
||||
},
|
||||
"baldi": {
|
||||
"name": "Baldi's Basics",
|
||||
"image": "/games/baldi/logo.png",
|
||||
"slug": "baldi"
|
||||
},
|
||||
"cannon-basketball-4": {
|
||||
"name": "Cannon Basketball 4",
|
||||
"image": "/games/cannon-basketball-4/logo.png",
|
||||
"slug": "cannon-basketball-4"
|
||||
},
|
||||
"cell-machine": {
|
||||
"name": "Cell Machine",
|
||||
"image": "/games/cell-machine/logo.png",
|
||||
"slug": "cell-machine"
|
||||
},
|
||||
"chrome-dino": {
|
||||
"name": "Chrome Dino",
|
||||
"image": "/games/chrome-dino/logo.png",
|
||||
"slug": "chrome-dino"
|
||||
},
|
||||
"cookie-clicker": {
|
||||
"name": "Cookie Clicker",
|
||||
"image": "/games/cookie-clicker/logo.png",
|
||||
"slug": "cookie-clicker"
|
||||
},
|
||||
"csgo-clicker": {
|
||||
"name": "CSGO Clicker",
|
||||
"image": "/games/csgo-clicker/logo.png",
|
||||
"slug": "csgo-clicker"
|
||||
},
|
||||
"ctr": {
|
||||
"name": "Cut The Rope",
|
||||
"image": "/games/ctr/logo.png",
|
||||
"slug": "ctr"
|
||||
},
|
||||
"ctr-holiday": {
|
||||
"name": "Cut The Rope - Holiday",
|
||||
"image": "/games/ctr-holiday/logo.png",
|
||||
"slug": "ctr-holiday"
|
||||
},
|
||||
"ctr-tr": {
|
||||
"name": "Cut The Rope - Time Travel",
|
||||
"image": "/games/ctr-tr/logo.png",
|
||||
"slug": "ctr-tr"
|
||||
},
|
||||
"death-run-3d": {
|
||||
"name": "Death Run 3D",
|
||||
"image": "/games/death-run-3d/logo.png",
|
||||
"slug": "death-run-3d"
|
||||
},
|
||||
"doge-miner": {
|
||||
"name": "Doge Miner",
|
||||
"image": "/games/doge-miner/logo.png",
|
||||
"slug": "doge-miner"
|
||||
},
|
||||
"doodle-jump": {
|
||||
"name": "Doodle Jump",
|
||||
"image": "/games/doodle-jump/logo.png",
|
||||
"slug": "doodle-jump"
|
||||
},
|
||||
"doom": {
|
||||
"name": "Doom",
|
||||
"image": "/games/doom/logo.png",
|
||||
"slug": "doom"
|
||||
},
|
||||
"draw-the-hill": {
|
||||
"name": "Draw The Hill",
|
||||
"image": "/games/draw-the-hill/logo.png",
|
||||
"slug": "draw-the-hill"
|
||||
},
|
||||
"evil-glitch": {
|
||||
"name": "Evil Glitch",
|
||||
"image": "/games/evil-glitch/logo.png",
|
||||
"slug": "evil-glitch"
|
||||
},
|
||||
"fall-boys": {
|
||||
"name": "Fall Boys",
|
||||
"image": "/games/fall-boys/logo.png",
|
||||
"slug": "fall-boys"
|
||||
},
|
||||
"firewater": {
|
||||
"name": "Fireboy and Watergirl",
|
||||
"image": "/games/firewater/logo.png",
|
||||
"slug": "firewater"
|
||||
},
|
||||
"firewater2": {
|
||||
"name": "Fireboy and Watergirl 2",
|
||||
"image": "/games/firewater2/logo.png",
|
||||
"slug": "firewater2"
|
||||
},
|
||||
"fnaf": {
|
||||
"name": "Five Nights at Freddy's",
|
||||
"image": "/games/fnaf/logo.png",
|
||||
"slug": "fnaf"
|
||||
},
|
||||
"fnaf2": {
|
||||
"name": "Five Nights at Freddy's 2",
|
||||
"image": "/games/fnaf2/logo.png",
|
||||
"slug": "fnaf2"
|
||||
},
|
||||
"fnaf3": {
|
||||
"name": "Five Nights at Freddy's 3",
|
||||
"image": "/games/fnaf3/logo.png",
|
||||
"slug": "fnaf3"
|
||||
},
|
||||
"fnaf4": {
|
||||
"name": "Five Nights at Freddy's 4",
|
||||
"image": "/games/fnaf4/logo.png",
|
||||
"slug": "fnaf4"
|
||||
},
|
||||
"game-inside": {
|
||||
"name": "Game Inside",
|
||||
"image": "/games/game-inside/logo.png",
|
||||
"slug": "game-inside"
|
||||
},
|
||||
"google-snake": {
|
||||
"name": "Google Snake",
|
||||
"image": "/games/google-snake/logo.png",
|
||||
"slug": "google-snake"
|
||||
},
|
||||
"grindcraft": {
|
||||
"name": "Grindcraft",
|
||||
"image": "/games/grindcraft/logo.png",
|
||||
"slug": "grindcraft"
|
||||
},
|
||||
"idle-breakout": {
|
||||
"name": "Idle Breakout",
|
||||
"image": "/games/idle-breakout/logo.png",
|
||||
"slug": "idle-breakout"
|
||||
},
|
||||
"just-one-boss": {
|
||||
"name": "Just One Boss",
|
||||
"image": "/games/just-one-boss/logo.png",
|
||||
"slug": "just-one-boss"
|
||||
},
|
||||
"line-rider": {
|
||||
"name": "Line Rider",
|
||||
"image": "/games/line-rider/logo.png",
|
||||
"slug": "line-rider"
|
||||
},
|
||||
"minecraft-classic": {
|
||||
"name": "Minecraft Classic",
|
||||
"image": "/games/minecraft-classic/logo.png",
|
||||
"slug": "minecraft-classic"
|
||||
},
|
||||
"minesweeper": {
|
||||
"name": "Minesweeper",
|
||||
"image": "/games/minesweeper/logo.png",
|
||||
"slug": "minesweeper"
|
||||
},
|
||||
"moto-x3m": {
|
||||
"name": "Moto X3M",
|
||||
"image": "/games/moto-x3m/logo.png",
|
||||
"slug": "moto-x3m"
|
||||
},
|
||||
"moto-x3m-pool": {
|
||||
"name": "Moto X3M Pool Party",
|
||||
"image": "/games/moto-x3m-pool/logo.png",
|
||||
"slug": "moto-x3m-pool"
|
||||
},
|
||||
"moto-x3m-spooky": {
|
||||
"name": "Moto X3M Spooky Land",
|
||||
"image": "/games/moto-x3m-spooky/logo.png",
|
||||
"slug": "moto-x3m-spooky"
|
||||
},
|
||||
"moto-x3m-winter": {
|
||||
"name": "Moto X3M Winter",
|
||||
"image": "/games/moto-x3m-winter/logo.png",
|
||||
"slug": "moto-x3m-winter"
|
||||
},
|
||||
"osu": {
|
||||
"name": "osu!",
|
||||
"image": "/games/osu/logo.png",
|
||||
"slug": "osu"
|
||||
},
|
||||
"retro-bowl": {
|
||||
"name": "Retro Bowl",
|
||||
"image": "/games/retro-bowl/logo.png",
|
||||
"slug": "retro-bowl"
|
||||
},
|
||||
"slope": {
|
||||
"name": "Slope",
|
||||
"image": "/games/slope/logo.png",
|
||||
"slug": "slope"
|
||||
},
|
||||
"sm64": {
|
||||
"name": "Super Mario 64",
|
||||
"image": "/games/sm64/logo.png",
|
||||
"slug": "sm64"
|
||||
},
|
||||
"solitaire": {
|
||||
"name": "Solitaire",
|
||||
"image": "/games/solitaire/logo.png",
|
||||
"slug": "solitaire"
|
||||
},
|
||||
"superhot": {
|
||||
"name": "Superhot",
|
||||
"image": "/games/superhot/logo.png",
|
||||
"slug": "superhot"
|
||||
},
|
||||
"there-is-no-game": {
|
||||
"name": "There is No Game",
|
||||
"image": "/games/there-is-no-game/logo.png",
|
||||
"slug": "there-is-no-game"
|
||||
},
|
||||
"ul6": {
|
||||
"name": "Ultima 6",
|
||||
"image": "/games/ul6/logo.png",
|
||||
"slug": "ul6"
|
||||
},
|
||||
"vex3": {
|
||||
"name": "Vex 3",
|
||||
"image": "/games/vex3/logo.png",
|
||||
"slug": "vex3"
|
||||
},
|
||||
"vex4": {
|
||||
"name": "Vex 4",
|
||||
"image": "/games/vex4/logo.png",
|
||||
"slug": "vex4"
|
||||
},
|
||||
"vex5": {
|
||||
"name": "Vex 5",
|
||||
"image": "/games/vex5/logo.png",
|
||||
"slug": "vex5"
|
||||
},
|
||||
"vex6": {
|
||||
"name": "Vex 6",
|
||||
"image": "/games/vex6/logo.png",
|
||||
"slug": "vex6"
|
||||
},
|
||||
"worlds-hardest-game": {
|
||||
"name": "World's Hardest Game",
|
||||
"image": "/games/worlds-hardest-game/logo.png",
|
||||
"slug": "worlds-hardest-game"
|
||||
},
|
||||
"worlds-hardest-game-2": {
|
||||
"name": "World's Hardest Game 2",
|
||||
"image": "/games/worlds-hardest-game-2/logo.png",
|
||||
"slug": "worlds-hardest-game-2"
|
||||
},
|
||||
"you-are-bezos": {
|
||||
"name": "You are Bezos",
|
||||
"image": "/games/you-are-bezos/logo.png",
|
||||
"slug": "you-are-bezos"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,172 +1,192 @@
|
|||
---
|
||||
import { ViewTransitions } from 'astro:transitions';
|
||||
import Header from '../components/Header.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
import ThemeLoader from '../components/ThemeLoader.astro';
|
||||
import CloakLoader from '../components/CloakLoader.astro';
|
||||
import WelcomeLogging from '../components/WelcomeLogging.astro';
|
||||
import { ViewTransitions } from "astro:transitions";
|
||||
import Header from "../components/Header.astro";
|
||||
import Footer from "../components/Footer.astro";
|
||||
import ThemeLoader from "../components/ThemeLoader.astro";
|
||||
import CloakLoader from "../components/CloakLoader.astro";
|
||||
import WelcomeLogging from "../components/WelcomeLogging.astro";
|
||||
import UVRegistrar from "../components/ProxyRegistrar.astro";
|
||||
|
||||
type Preload = {
|
||||
"href": string
|
||||
"as": string
|
||||
}
|
||||
href: string;
|
||||
as: string;
|
||||
};
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
title: string;
|
||||
optionalPreloads?: Preload[];
|
||||
}
|
||||
|
||||
const { title, optionalPreloads } = Astro.props;
|
||||
---
|
||||
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="description" content="Astro description" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Varela+Round&display=swap" rel="stylesheet" as="style">
|
||||
{optionalPreloads?.map((item) => {
|
||||
return <link rel="preload" href={item.href} as={item.as} />
|
||||
})}
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>{title}</title>
|
||||
<ViewTransitions />
|
||||
<ThemeLoader />
|
||||
<head>
|
||||
<ThemeLoader transition:persist />
|
||||
<CloakLoader transition:persist />
|
||||
</head>
|
||||
<body>
|
||||
<Header></Header>
|
||||
<slot transition:animate={"fade"} />
|
||||
<WelcomeLogging />
|
||||
<Footer></Footer>
|
||||
</body>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="description" content="Astro description" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Varela+Round&display=swap"
|
||||
rel="stylesheet"
|
||||
as="style"
|
||||
/>
|
||||
{
|
||||
optionalPreloads?.map((item) => {
|
||||
return <link rel="preload" href={item.href} as={item.as} />;
|
||||
})
|
||||
}
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>{title}</title>
|
||||
<ViewTransitions />
|
||||
</head>
|
||||
<body>
|
||||
<Header />
|
||||
<slot transition:animate={"fade"} />
|
||||
<WelcomeLogging />
|
||||
<UVRegistrar />
|
||||
<Footer />
|
||||
<style is:global>
|
||||
:root {
|
||||
--background-color: #080808;
|
||||
--background-highlight: #252525;
|
||||
--accent-color: #6b00c9;
|
||||
--accent-color-brighter: #7e00e0;
|
||||
--text-color: #fff;
|
||||
--text-color-accent: #c7c7c7;
|
||||
--dropdown-background-color: #1e1e1e;
|
||||
}
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
opacity: 0;
|
||||
animation: fadeIn ease 0.4s forwards;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
[data-theme="mocha"] {
|
||||
/* Catppucin Mocha theme */
|
||||
--background-color: #1e1e2e;
|
||||
--background-highlight: #45475a;
|
||||
--accent-color: #181825;
|
||||
--accent-color-brighter: #242539;
|
||||
--text-color: #cdd6f4;
|
||||
--text-color-accent: #bac2de;
|
||||
--dropdown-background-color: #32324e;
|
||||
}
|
||||
|
||||
[data-theme="macchiato"] {
|
||||
/* Catppuccin Macchiato Theme */
|
||||
--background-color: #24273a;
|
||||
--background-highlight: #494d64;
|
||||
--accent-color: #1e2030;
|
||||
--accent-color-brighter: #2a2d42;
|
||||
--text-color: #cad3f5;
|
||||
--text-color-accent: #b8c0e0;
|
||||
--dropdown-background-color: #323550;
|
||||
}
|
||||
|
||||
[data-theme="rose_pine"] {
|
||||
/* Rosé Pine Theme */
|
||||
--background-color: #191724;
|
||||
--background-highlight: #1f1d2e;
|
||||
--accent-color: #26233a;
|
||||
--accent-color-brighter: #2e2b4a;
|
||||
--text-color: #e0def4;
|
||||
--text-color-accent: #c7c5e0;
|
||||
--dropdown-background-color: #1f1d2e;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
font-family: "Varela Round", sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--background-color);
|
||||
max-width: 100vw;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
body > * {
|
||||
opacity: 1;
|
||||
}
|
||||
.title-text {
|
||||
color: var(--text-color);
|
||||
text-align: center;
|
||||
font-weight: 400;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.main-content {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 60vh;
|
||||
}
|
||||
#proxy-frame {
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
width: 100vw;
|
||||
height: 95vh;
|
||||
top: 5vh;
|
||||
left: 0;
|
||||
border: none;
|
||||
background-color: var(--background-color);
|
||||
transition: opacity 250ms ease-in-out;
|
||||
pointer-events: none;
|
||||
}
|
||||
#proxy-frame {
|
||||
opacity: 0;
|
||||
}
|
||||
.top-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 1rem;
|
||||
height: 5vh;
|
||||
background-color: var(--accent-color);
|
||||
color: var(--text-color);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
z-index: 100;
|
||||
transition: opacity 350ms ease-in-out;
|
||||
pointer-events: none;
|
||||
}
|
||||
.close-button {
|
||||
padding: 5px;
|
||||
padding-inline: 40px;
|
||||
border: none;
|
||||
background-color: var(--background-highlight);
|
||||
color: var(--text-color-accent);
|
||||
border-radius: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
||||
<style is:global>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
opacity: 0;
|
||||
animation: fadeIn ease 0.15s forwards;
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
--background-color: #080808;
|
||||
--background-highlight: #252525;
|
||||
--accent-color: #6b00c9;
|
||||
--accent-color-brighter: #8800ff;
|
||||
--text-color: #fff;
|
||||
--text-color-accent: #c7c7c7;
|
||||
--dropdown-background-color: #1e1e1e;
|
||||
}
|
||||
|
||||
[data-theme="mocha"] {
|
||||
/* Catppucin Mocha theme */
|
||||
--background-color: #1e1e2e;
|
||||
--background-highlight: #45475a;
|
||||
--accent-color: #181825;
|
||||
--accent-color-brighter: #242539;
|
||||
--text-color: #cdd6f4;
|
||||
--text-color-accent: #bac2de;
|
||||
--dropdown-background-color: #32324e;
|
||||
}
|
||||
|
||||
[data-theme="macchiato"] {
|
||||
/* Catppuccin Macchiato Theme */
|
||||
--background-color: #24273a;
|
||||
--background-highlight: #494d64;
|
||||
--accent-color: #1e2030;
|
||||
--accent-color-brighter: #525571;
|
||||
--text-color: #cad3f5;
|
||||
--text-color-accent: #b8c0e0;
|
||||
--dropdown-background-color: #323550;
|
||||
}
|
||||
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
font-family: 'Varela Round', sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--background-color);
|
||||
max-width: 100vw;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
body > * {
|
||||
opacity: 1;
|
||||
}
|
||||
.title-text {
|
||||
color: var(--text-color);
|
||||
text-align: center;
|
||||
font-weight: 400;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.main-content {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 60vh;
|
||||
}
|
||||
#proxy-frame {
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
width: 100vw;
|
||||
height: 95vh;
|
||||
top: 5vh;
|
||||
border: none;
|
||||
background-color: var(--background-color);
|
||||
transition: opacity 250ms ease-in-out;
|
||||
pointer-events: none;
|
||||
}
|
||||
#proxy-frame {
|
||||
opacity: 0;
|
||||
}
|
||||
.top-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 1rem;
|
||||
height: 5vh;
|
||||
background-color: var(--accent-color);
|
||||
color: var(--text-color);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
z-index: 100;
|
||||
transition: opacity 350ms ease-in-out;
|
||||
pointer-events: none;
|
||||
}
|
||||
.close-button {
|
||||
padding: 5px;
|
||||
padding-inline: 40px;
|
||||
border: none;
|
||||
background-color: var(--background-highlight);
|
||||
color: var(--text-color-accent);
|
||||
border-radius: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@ import Layout from "../layouts/Layout.astro";
|
|||
---
|
||||
|
||||
<Layout title="404 | Alu">
|
||||
<div class="main-content error-page">
|
||||
<h1>404!</h1>
|
||||
<p>The content you have requested could not be found!</p>
|
||||
</div>
|
||||
<div class="main-content error-page">
|
||||
<h1>404!</h1>
|
||||
<p>The content you have requested could not be found!</p>
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
.error-page {
|
||||
color: white
|
||||
}
|
||||
</style>
|
||||
.error-page {
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,80 +1,31 @@
|
|||
---
|
||||
import Layout from "../../layouts/Layout.astro";
|
||||
import games from "../../json/games.json";
|
||||
import GameItem from "../../components/GameItem.astro";
|
||||
|
||||
import { getLangFromUrl, useTranslations } from "../../i18n/utils"
|
||||
import { getLangFromUrl, useTranslations } from "../../i18n/utils";
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const t = useTranslations(lang);
|
||||
|
||||
export function getStaticPaths () {
|
||||
return [
|
||||
{params: {lang: 'en'}},
|
||||
{params: {lang: 'jp'}},
|
||||
];
|
||||
export function getStaticPaths() {
|
||||
return [{ params: { lang: "en" } }, { params: { lang: "jp" } }];
|
||||
}
|
||||
---
|
||||
|
||||
<Layout title={t("pages.games")}>
|
||||
<h1 class="title-text">{t("games.title")}</h1>
|
||||
<div class="grid">
|
||||
<GameItem name="1v1.lol" image="/games/1v1.lol/logo.png"></GameItem>
|
||||
<GameItem name="2048" image="/games/2048/logo.png"></GameItem>
|
||||
<GameItem name="The Backrooms" image="/games/backrooms/logo.png" slugName="backrooms"></GameItem>
|
||||
<GameItem name="Baldi's Basics" image="/games/baldi/logo.png" slugName="baldi"></GameItem>
|
||||
<GameItem name="Cannon Basketball 4" image="/games/cannon-basketball-4/logo.png" slugName="cannon-basketball-4"></GameItem>
|
||||
<GameItem name="Cell Machine" image="/games/cell-machine/logo.png" slugName="cell-machine"></GameItem>
|
||||
<GameItem name="Chrome Dino" image="/games/chrome-dino/logo.png" slugName="chrome-dino"></GameItem>
|
||||
<GameItem name="Cookie Clicker" image="/games/cookie-clicker/logo.png" slugName="cookie-clicker"></GameItem>
|
||||
<GameItem name="CSGO Clicker" image="/games/csgo-clicker/logo.png" slugName="csgo-clicker"></GameItem>
|
||||
<GameItem name="Cut The Rope" image="/games/ctr/logo.png" slugName="ctr"></GameItem>
|
||||
<GameItem name="Cut The Rope - Holiday" image="/games/ctr-holiday/logo.png" slugName="ctr-holiday"></GameItem>
|
||||
<GameItem name="Cut The Rope - Time Travel" image="/games/ctr-tr/logo.png" slugName="ctr-tr"></GameItem>
|
||||
<GameItem name="Death Run 3D" image="/games/death-run-3d/logo.png" slugName="death-run-3d"></GameItem>
|
||||
<GameItem name="Doge Miner" image="/games/doge-miner/logo.png" slugName="doge-miner"></GameItem>
|
||||
<GameItem name="Doodle Jump" image="/games/doodle-jump/logo.png" slugName="doodle-jump"></GameItem>
|
||||
<GameItem name="Doom" image="/games/doom/logo.png" slugName="doom"></GameItem>
|
||||
<GameItem name="Draw The Hill" image="/games/draw-the-hill/logo.png" slugName="draw-the-hill"></GameItem>
|
||||
<GameItem name="Evil Glitch" image="/games/evil-glitch/logo.png" slugName="evil-glitch"></GameItem>
|
||||
<GameItem name="Fall Boys" image="/games/fall-boys/logo.png" slugName="fall-boys"></GameItem>
|
||||
<GameItem name="Fireboy and Watergirl" image="/games/firewater/logo.png" slugName="firewater"></GameItem>
|
||||
<GameItem name="Fireboy and Watergirl 2" image="/games/firewater2/logo.png" slugName="firewater2"></GameItem>
|
||||
<GameItem name="Five Nights at Freddy's" image="/games/fnaf/logo.png" slugName="fnaf"></GameItem>
|
||||
<GameItem name="Five Nights at Freddy's 2" image="/games/fnaf2/logo.png" slugName="fnaf2"></GameItem>
|
||||
<GameItem name="Five Nights at Freddy's 3" image="/games/fnaf3/logo.png" slugName="fnaf3"></GameItem>
|
||||
<GameItem name="Five Nights at Freddy's 4" image="/games/fnaf4/logo.png" slugName="fnaf4"></GameItem>
|
||||
<GameItem name="Game Inside" image="/games/game-inside/logo.png" slugName="game-inside"></GameItem>
|
||||
<GameItem name="Google Snake" image="/games/google-snake/logo.png" slugName="google-snake"></GameItem>
|
||||
<GameItem name="Grindcraft" image="/games/grindcraft/logo.png" slugName="grindcraft"></GameItem>
|
||||
<GameItem name="Idle Breakout" image="/games/idle-breakout/logo.png" slugName="idle-breakout"></GameItem>
|
||||
<GameItem name="Just One Boss" image="/games/just-one-boss/logo.png" slugName="just-one-boss"></GameItem>
|
||||
<GameItem name="Line Rider" image="/games/line-rider/logo.png" slugName="line-rider"></GameItem>
|
||||
<GameItem name="Minecraft Classic" image="/games/minecraft-classic/logo.png" slugName="minecraft-classic"></GameItem>
|
||||
<GameItem name="Minesweeper" image="/games/minesweeper/logo.png" slugName="minesweeper"></GameItem>
|
||||
<GameItem name="Moto X3M" image="/games/moto-x3m/logo.png" slugName="moto-x3m"></GameItem>
|
||||
<GameItem name="Moto X3M Pool Party" image="/games/moto-x3m-pool/logo.png" slugName="moto-x3m-pool"></GameItem>
|
||||
<GameItem name="Moto X3M Spooky Land" image="/games/moto-x3m-spooky/logo.png" slugName="moto-x3m-spooky"></GameItem>
|
||||
<GameItem name="Moto X3M Winter" image="/games/moto-x3m-winter/logo.png" slugName="moto-x3m-winter"></GameItem>
|
||||
<GameItem name="osu!" image="/games/osu/logo.png" slugName="osu"></GameItem>
|
||||
<GameItem name="Retro Bowl" image="/games/retro-bowl/logo.png" slugName="retro-bowl"></GameItem>
|
||||
<GameItem name="Slope" image="/games/slope/logo.png" slugName="slope"></GameItem>
|
||||
<GameItem name="Super Mario 64" image="/games/sm64/logo.png" slugName="sm64"></GameItem>
|
||||
<GameItem name="Solitaire" image="/games/solitaire/logo.png" slugName="solitaire"></GameItem>
|
||||
<GameItem name="Superhot" image="/games/superhot/logo.png" slugName="superhot"></GameItem>
|
||||
<GameItem name="There is No Game" image="/games/there-is-no-game/logo.png" slugName="there-is-no-game"></GameItem>
|
||||
<GameItem name="Ultima 6" image="/games/ul6/logo.png" slugName="ul6"></GameItem>
|
||||
<GameItem name="Vex 3" image="/games/vex3/logo.png" slugName="vex3"></GameItem>
|
||||
<GameItem name="Vex 4" image="/games/vex4/logo.png" slugName="vex4"></GameItem>
|
||||
<GameItem name="Vex 5" image="/games/vex5/logo.png" slugName="vex5"></GameItem>
|
||||
<GameItem name="Vex 6" image="/games/vex6/logo.png" slugName="vex6"></GameItem>
|
||||
<GameItem name="World's Hardest Game" image="/games/worlds-hardest-game/logo.png" slugName="worlds-hardest-game"></GameItem>
|
||||
<GameItem name="World's Hardest Game 2" image="/games/worlds-hardest-game-2/logo.png" slugName="worlds-hardest-game-2"></GameItem>
|
||||
<GameItem name="You are Bezos" image="/games/you-are-bezos/logo.png" slugName="you-are-bezos"></GameItem>
|
||||
</div>
|
||||
<h1 class="title-text">{t("games.title")}</h1>
|
||||
<div class="grid">
|
||||
{
|
||||
Object.keys(games).map((key) => {
|
||||
const game = (games as any)[key];
|
||||
return <GameItem name={game.name} image={game.image} slugName={game.slug} />;
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
|
||||
.grid {
|
||||
.grid {
|
||||
color: var(--text-color);
|
||||
margin-top: -10px;
|
||||
height: max-content;
|
||||
|
|
@ -86,18 +37,18 @@ export function getStaticPaths () {
|
|||
justify-content: center;
|
||||
gap: 1rem;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 973px) {
|
||||
.grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 467px) {
|
||||
@media only screen and (max-width: 973px) {
|
||||
.grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 467px) {
|
||||
.grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,75 +1,70 @@
|
|||
---
|
||||
import Layout from "../../layouts/Layout.astro";
|
||||
import UVRegistrar from "../../components/UVRegistrar.astro";
|
||||
|
||||
import { getLangFromUrl, useTranslations } from "../../i18n/utils"
|
||||
import { getLangFromUrl, useTranslations } from "../../i18n/utils";
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const t = useTranslations(lang);
|
||||
|
||||
export function getStaticPaths () {
|
||||
return [
|
||||
{params: {lang: 'en'}},
|
||||
{params: {lang: 'jp'}},
|
||||
];
|
||||
export function getStaticPaths() {
|
||||
return [{ params: { lang: "en" } }, { params: { lang: "jp" } }];
|
||||
}
|
||||
---
|
||||
|
||||
<Layout title={t("pages.home")}>
|
||||
<div class="main-content">
|
||||
<h1 class="title-text">{t("menu.welcome")}</h1>
|
||||
<div class="main-content">
|
||||
<h1 class="title-text">{t("menu.welcome")}</h1>
|
||||
<form class="url-input-form" id="url-input-form">
|
||||
<input class="url-input" type="text" placeholder={t("menu.search")}>
|
||||
<input class="url-input" type="text" placeholder={t("menu.search")} />
|
||||
<div id="loading-content">Loading...</div>
|
||||
<div id="top-bar"></div>
|
||||
<iframe title="proxy-iframe" id="proxy-frame"></iframe>
|
||||
</form>
|
||||
</div>
|
||||
<UVRegistrar></UVRegistrar>
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
form {
|
||||
width: 30%;
|
||||
}
|
||||
form {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 38px;
|
||||
}
|
||||
.title-text {
|
||||
font-size: 38px;
|
||||
}
|
||||
|
||||
.url-input-form {
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
.url-input-form {
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.url-input {
|
||||
display: block;
|
||||
background: transparent url("/img/search.svg") no-repeat 13px center;
|
||||
}
|
||||
.url-input {
|
||||
display: block;
|
||||
background: transparent url("/img/search.svg") no-repeat 13px center;
|
||||
}
|
||||
|
||||
.url-input {
|
||||
background-color: #080808;
|
||||
color: #D8DEE9;
|
||||
border: 3px solid white;
|
||||
border-radius: 30px;
|
||||
padding: 15px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
transition: 400ms ease-out;
|
||||
outline: none;
|
||||
font-family: 'Varela Round', sans-serif;
|
||||
font-size: 16px;
|
||||
}
|
||||
.url-input {
|
||||
background-color: var(--dropdown-background-color);
|
||||
color: var(--text-color);
|
||||
border: 3px solid var(--text-color);
|
||||
border-radius: 30px;
|
||||
padding: 15px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
transition: 400ms ease-out;
|
||||
outline: none;
|
||||
font-family: "Varela Round", sans-serif;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.url-input::placeholder {
|
||||
color: #D8DEE9;
|
||||
}
|
||||
.url-input::placeholder {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
#loading-content {
|
||||
color: white;
|
||||
padding: 8px;
|
||||
position: relative;
|
||||
opacity: 0;
|
||||
transition: 250ms ease-in-out;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
#loading-content {
|
||||
color: var(--text-color);
|
||||
padding: 8px;
|
||||
position: relative;
|
||||
opacity: 0;
|
||||
transition: 250ms ease-in-out;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -2,25 +2,22 @@
|
|||
import SettingsTablist from "../../components/SettingsTablist.astro";
|
||||
import Layout from "../../layouts/Layout.astro";
|
||||
|
||||
import { getLangFromUrl, useTranslations } from "../../i18n/utils"
|
||||
import { getLangFromUrl, useTranslations } from "../../i18n/utils";
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const t = useTranslations(lang);
|
||||
|
||||
export function getStaticPaths () {
|
||||
return [
|
||||
{params: {lang: 'en'}},
|
||||
{params: {lang: 'jp'}},
|
||||
];
|
||||
export function getStaticPaths() {
|
||||
return [{ params: { lang: "en" } }, { params: { lang: "jp" } }];
|
||||
}
|
||||
---
|
||||
|
||||
<Layout title={t("pages.settings")}>
|
||||
<h1 class="title-text">Settings</h1>
|
||||
<SettingsTablist />
|
||||
<h1 class="title-text">Settings</h1>
|
||||
<SettingsTablist />
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
font-size: 40px;
|
||||
}
|
||||
</style>
|
||||
h1 {
|
||||
font-size: 40px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
---
|
||||
import { ViewTransitions } from "astro:transitions";
|
||||
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
|
|
@ -13,24 +12,23 @@ import { ViewTransitions } from "astro:transitions";
|
|||
let currentLang = localStorage.getItem("alu__selectedLanguage");
|
||||
if (currentLang) {
|
||||
try {
|
||||
let parsed = JSON.parse(currentLang).value
|
||||
let parsed = JSON.parse(currentLang).value;
|
||||
switch (parsed) {
|
||||
case "en":
|
||||
window.location.href = "/en/";
|
||||
break;
|
||||
window.location.href = "/en/";
|
||||
break;
|
||||
case "jp":
|
||||
window.location.href = "/jp/";
|
||||
break;
|
||||
window.location.href = "/jp/";
|
||||
break;
|
||||
default:
|
||||
window.location.href = "/en/";
|
||||
break;
|
||||
}
|
||||
window.location.href = "/en/";
|
||||
break;
|
||||
}
|
||||
} catch {
|
||||
localStorage.clear();
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body></body>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/strict"
|
||||
}
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"compilerOptions": {
|
||||
"verbatimModuleSyntax": false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue