Add support for optionally enabling masqr via .env and optionally enabling wisp, format using prettier.
This commit is contained in:
parent
f1a56b9f91
commit
f8bde78717
15 changed files with 4356 additions and 1803 deletions
3
.env.example
Normal file
3
.env.example
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
USE_WISP=true
|
||||||
|
MASQR_ENABLED=true
|
||||||
|
PORT=3000
|
||||||
|
|
@ -20,7 +20,7 @@ Alu is a beautiful, functional, and sleek web proxy, which focuses on customizat
|
||||||
|
|
||||||
Deploying Alu is about as simple as it gets, from your terminal, type
|
Deploying Alu is about as simple as it gets, from your terminal, type
|
||||||
|
|
||||||
`git clone https://github.com/wearrrrr/Alu --recurse-submodules`
|
`git clone https://github.com/titaniumnetwork-dev/Alu --recurse-submodules`
|
||||||
|
|
||||||
This command should clone Alu's frontend, as well as [alu-games](https://github.com/wearrrrr/alu-games). If you wish to skip cloning games, then leave out the last flag.
|
This command should clone Alu's frontend, as well as [alu-games](https://github.com/wearrrrr/alu-games). If you wish to skip cloning games, then leave out the last flag.
|
||||||
|
|
||||||
|
|
@ -39,6 +39,7 @@ Congrats, you've now deployed your very own web proxy!
|
||||||
- Typescript
|
- Typescript
|
||||||
- ExpressJS
|
- ExpressJS
|
||||||
- Prettier
|
- Prettier
|
||||||
|
- ESLint
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
|
|
|
||||||
85
index.js
85
index.js
|
|
@ -13,13 +13,14 @@ import { existsSync } from "fs";
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
import cookieParser from "cookie-parser";
|
import cookieParser from "cookie-parser";
|
||||||
import wisp from "wisp-server-node";
|
import wisp from "wisp-server-node";
|
||||||
import fs from "node:fs";
|
|
||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
|
import { masqrCheck } from "./masqr.js";
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
|
const whiteListedDomains = ["aluu.xyz", "localhost:3000"];
|
||||||
const LICENSE_SERVER_URL = "https://license.mercurywork.shop/validate?license=";
|
const LICENSE_SERVER_URL = "https://license.mercurywork.shop/validate?license=";
|
||||||
const whiteListedDomains = ["aluu.xyz", "localhost:3000"]; // Add any public domains you have here
|
const WISP_ENABLED = process.env.USE_WISP;
|
||||||
const failureFile = fs.readFileSync("Checkfailed.html", "utf8");
|
const MASQR_ENABLED = process.env.MASQR_ENABLED;
|
||||||
|
|
||||||
if (!existsSync("./dist")) build();
|
if (!existsSync("./dist")) build();
|
||||||
|
|
||||||
|
|
@ -49,71 +50,12 @@ const app = express();
|
||||||
app.use(compression({ threshold: 0, filter: () => true }));
|
app.use(compression({ threshold: 0, filter: () => true }));
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
|
|
||||||
async function MasqFail(req, res) {
|
// Set process.env.MASQR_ENABLED to "true" to enable masqr protection.
|
||||||
if (!req.headers.host) {
|
if (process.env.MASQR_ENABLED == "true") {
|
||||||
return;
|
console.log(chalk.gray("Starting Masqr..."));
|
||||||
}
|
app.use(await masqrCheck({ whitelist: whiteListedDomains, licenseServer: LICENSE_SERVER_URL }));
|
||||||
const unsafeSuffix = req.headers.host + ".html";
|
|
||||||
let safeSuffix = path.normalize(unsafeSuffix).replace(/^(\.\.(\/|\\|$))+/, "");
|
|
||||||
let safeJoin = path.join(process.cwd() + "/Masqrd", safeSuffix);
|
|
||||||
try {
|
|
||||||
await fs.promises.access(safeJoin); // man do I wish this was an if-then instead of a "exception on fail"
|
|
||||||
const failureFileLocal = await fs.promises.readFile(safeJoin, "utf8");
|
|
||||||
res.setHeader("Content-Type", "text/html");
|
|
||||||
res.send(failureFileLocal);
|
|
||||||
return;
|
|
||||||
} catch (e) {
|
|
||||||
res.setHeader("Content-Type", "text/html");
|
|
||||||
res.send(failureFile);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Woooooo masqr yayyyy (said no one)
|
|
||||||
// uncomment for masqr
|
|
||||||
app.use(async (req, res, next) => {
|
|
||||||
if (req.headers.host && whiteListedDomains.includes(req.headers.host)) {
|
|
||||||
next();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const authheader = req.headers.authorization;
|
|
||||||
if (req.cookies["authcheck"]) {
|
|
||||||
next();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req.cookies["refreshcheck"] != "true") {
|
|
||||||
res.cookie("refreshcheck", "true", { maxAge: 10000 }); // 10s refresh check
|
|
||||||
MasqFail(req, res);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!authheader) {
|
|
||||||
res.setHeader("WWW-Authenticate", "Basic"); // Yeah so we need to do this to get the auth params, kinda annoying and just showing a login prompt gives it away so its behind a 10s refresh check
|
|
||||||
res.status(401);
|
|
||||||
MasqFail(req, res);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auth = Buffer.from(authheader.split(" ")[1], "base64").toString().split(":");
|
|
||||||
const pass = auth[1];
|
|
||||||
|
|
||||||
const licenseCheck = (
|
|
||||||
await (await fetch(LICENSE_SERVER_URL + pass + "&host=" + req.headers.host)).json()
|
|
||||||
)["status"];
|
|
||||||
console.log(
|
|
||||||
LICENSE_SERVER_URL + pass + "&host=" + req.headers.host + " returned " + licenseCheck
|
|
||||||
);
|
|
||||||
if (licenseCheck == "License valid") {
|
|
||||||
res.cookie("authcheck", "true", { expires: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000) }); // authorize session, for like a year, by then the link will be expired lol
|
|
||||||
res.send(`<script> window.location.href = window.location.href </script>`); // fun hack to make the browser refresh and remove the auth params from the URL
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MasqFail(req, res);
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
|
|
||||||
app.use(express.static(path.join(process.cwd(), "static")));
|
app.use(express.static(path.join(process.cwd(), "static")));
|
||||||
app.use(express.static(path.join(process.cwd(), "build")));
|
app.use(express.static(path.join(process.cwd(), "build")));
|
||||||
app.use("/uv/", express.static(uvPath));
|
app.use("/uv/", express.static(uvPath));
|
||||||
|
|
@ -127,7 +69,7 @@ app.use(
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
app.use((req, res, next) => {
|
app.use((req, res, next) => {
|
||||||
if (req.url.includes ("/games/")) {
|
if (req.url.includes("/games/")) {
|
||||||
res.header("Cross-Origin-Opener-Policy", "same-origin");
|
res.header("Cross-Origin-Opener-Policy", "same-origin");
|
||||||
res.header("Cross-Origin-Embedder-Policy", "require-corp");
|
res.header("Cross-Origin-Embedder-Policy", "require-corp");
|
||||||
}
|
}
|
||||||
|
|
@ -136,11 +78,11 @@ app.use((req, res, next) => {
|
||||||
app.use("/custom-favicon", async (req, res) => {
|
app.use("/custom-favicon", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { url, contentType } = req.query;
|
const { url, contentType } = req.query;
|
||||||
const urlExt = url.split('.').pop();
|
const urlExt = url.split(".").pop();
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
const arrayBuffer = await response.arrayBuffer();
|
const arrayBuffer = await response.arrayBuffer();
|
||||||
const buffer = Buffer.from(arrayBuffer);
|
const buffer = Buffer.from(arrayBuffer);
|
||||||
console.log(contentType)
|
console.log(contentType);
|
||||||
if (contentType || !contentType == "") {
|
if (contentType || !contentType == "") {
|
||||||
res.setHeader("Content-Type", contentType);
|
res.setHeader("Content-Type", contentType);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -197,7 +139,7 @@ app.get("/search", async (req, res) => {
|
||||||
res.redirect(302, "/404.html");
|
res.redirect(302, "/404.html");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
app.get("*", function (req, res) {
|
app.get("*", (req, res) => {
|
||||||
res.sendFile(path.join(process.cwd(), "dist/client/404.html"));
|
res.sendFile(path.join(process.cwd(), "dist/client/404.html"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -217,7 +159,8 @@ server.on("upgrade", (req, socket, head) => {
|
||||||
bare.routeUpgrade(req, socket, head);
|
bare.routeUpgrade(req, socket, head);
|
||||||
} else if (shouldRouteRh(req)) {
|
} else if (shouldRouteRh(req)) {
|
||||||
routeRhUpgrade(req, socket, head);
|
routeRhUpgrade(req, socket, head);
|
||||||
} else if (req.url.endsWith("/wisp/")) {
|
/* Kinda hacky, I need to do a proper dynamic import. */
|
||||||
|
} else if (req.url.endsWith("/wisp/") && WISP_ENABLED == "true") {
|
||||||
wisp.routeRequest(req, socket, head);
|
wisp.routeRequest(req, socket, head);
|
||||||
} else {
|
} else {
|
||||||
socket.end();
|
socket.end();
|
||||||
|
|
|
||||||
68
masqr.js
Normal file
68
masqr.js
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
const failureFile = fs.readFileSync("Checkfailed.html", "utf8");
|
||||||
|
|
||||||
|
export async function masqrCheck(config) {
|
||||||
|
return async (req, res, next) => {
|
||||||
|
if (req.headers.host && config.whitelist.includes(req.headers.host)) {
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const authheader = req.headers.authorization;
|
||||||
|
if (req.cookies["authcheck"]) {
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.cookies["refreshcheck"] != "true") {
|
||||||
|
res.cookie("refreshcheck", "true", { maxAge: 10000 }); // 10s refresh check
|
||||||
|
MasqFail(req, res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!authheader) {
|
||||||
|
res.setHeader("WWW-Authenticate", "Basic");
|
||||||
|
res.status(401);
|
||||||
|
MasqFail(req, res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auth = Buffer.from(authheader.split(" ")[1], "base64").toString().split(":");
|
||||||
|
const pass = auth[1];
|
||||||
|
|
||||||
|
const licenseCheck = (
|
||||||
|
await (await fetch(config.licenseServer + pass + "&host=" + req.headers.host)).json()
|
||||||
|
)["status"];
|
||||||
|
console.log(
|
||||||
|
config.licenseServer + pass + "&host=" + req.headers.host + " returned " + licenseCheck
|
||||||
|
);
|
||||||
|
if (licenseCheck == "License valid") {
|
||||||
|
res.cookie("authcheck", "true", { expires: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000) }); // authorize session, for like a year, by then the link will be expired lol
|
||||||
|
res.send(`<script> window.location.href = window.location.href </script>`); // fun hack to make the browser refresh and remove the auth params from the URL
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MasqFail(req, res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function MasqFail(req, res) {
|
||||||
|
if (!req.headers.host) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const unsafeSuffix = req.headers.host + ".html";
|
||||||
|
let safeSuffix = path.normalize(unsafeSuffix).replace(/^(\.\.(\/|\\|$))+/, "");
|
||||||
|
let safeJoin = path.join(process.cwd() + "/Masqrd", safeSuffix);
|
||||||
|
try {
|
||||||
|
await fs.promises.access(safeJoin); // man do I wish this was an if-then instead of a "exception on fail"
|
||||||
|
const failureFileLocal = await fs.promises.readFile(safeJoin, "utf8");
|
||||||
|
res.setHeader("Content-Type", "text/html");
|
||||||
|
res.send(failureFileLocal);
|
||||||
|
return;
|
||||||
|
} catch (e) {
|
||||||
|
res.setHeader("Content-Type", "text/html");
|
||||||
|
res.send(failureFile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
5760
pnpm-lock.yaml
generated
5760
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
18
public/sw.js
18
public/sw.js
|
|
@ -7,13 +7,13 @@ importScripts(__uv$config.sw);
|
||||||
|
|
||||||
const uv = new UVServiceWorker();
|
const uv = new UVServiceWorker();
|
||||||
|
|
||||||
self.addEventListener('fetch', event => {
|
self.addEventListener("fetch", (event) => {
|
||||||
event.respondWith(
|
event.respondWith(
|
||||||
(async ()=>{
|
(async () => {
|
||||||
if(event.request.url.startsWith(location.origin + __uv$config.prefix)) {
|
if (event.request.url.startsWith(location.origin + __uv$config.prefix)) {
|
||||||
return await uv.fetch(event);
|
return await uv.fetch(event);
|
||||||
}
|
}
|
||||||
return await fetch(event.request);
|
return await fetch(event.request);
|
||||||
})()
|
})()
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,21 @@
|
||||||
/* latin-ext */
|
/* latin-ext */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Varela Round';
|
font-family: "Varela Round";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url(varela-latin-ext.woff2) format('woff2');
|
src: url(varela-latin-ext.woff2) format("woff2");
|
||||||
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
|
||||||
}
|
U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||||
/* latin */
|
}
|
||||||
@font-face {
|
/* latin */
|
||||||
font-family: 'Varela Round';
|
@font-face {
|
||||||
font-style: normal;
|
font-family: "Varela Round";
|
||||||
font-weight: 400;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-weight: 400;
|
||||||
src: url(varela-latin.woff2) format('woff2');
|
font-display: swap;
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
src: url(varela-latin.woff2) format("woff2");
|
||||||
}
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
|
||||||
|
U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
|
||||||
|
U+FFFD;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,9 @@
|
||||||
let iframe = document.getElementById("proxy-frame") as HTMLIFrameElement;
|
let iframe = document.getElementById("proxy-frame") as HTMLIFrameElement;
|
||||||
let topbar = document.getElementById("top-bar") as HTMLDivElement;
|
let topbar = document.getElementById("top-bar") as HTMLDivElement;
|
||||||
let closeButton = document.getElementById("close-button") as HTMLButtonElement;
|
let closeButton = document.getElementById("close-button") as HTMLButtonElement;
|
||||||
let backwardsButton = document.getElementById('nav-backwards') as HTMLImageElement;
|
let backwardsButton = document.getElementById("nav-backwards") as HTMLImageElement;
|
||||||
let forwardsButton = document.getElementById('nav-forwards') as HTMLImageElement;
|
let forwardsButton = document.getElementById("nav-forwards") as HTMLImageElement;
|
||||||
let shareButton = document.getElementById('nav-share') as HTMLImageElement;
|
let shareButton = document.getElementById("nav-share") as HTMLImageElement;
|
||||||
let preference = getProxyPreference();
|
let preference = getProxyPreference();
|
||||||
if (preference === "ultraviolet") {
|
if (preference === "ultraviolet") {
|
||||||
iframe.src = window.__uv$config.prefix + window.__uv$config.encodeUrl(url);
|
iframe.src = window.__uv$config.prefix + window.__uv$config.encodeUrl(url);
|
||||||
|
|
@ -114,7 +114,15 @@
|
||||||
iframe.classList.add("proxy-frame");
|
iframe.classList.add("proxy-frame");
|
||||||
document.body.appendChild(iframe);
|
document.body.appendChild(iframe);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
iframeLoad(iframe, loadingContent, topbar, closeButton, shareButton, forwardsButton, backwardsButton);
|
iframeLoad(
|
||||||
|
iframe,
|
||||||
|
loadingContent,
|
||||||
|
topbar,
|
||||||
|
closeButton,
|
||||||
|
shareButton,
|
||||||
|
forwardsButton,
|
||||||
|
backwardsButton
|
||||||
|
);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
function setActive() {
|
function setActive() {
|
||||||
|
|
@ -162,9 +170,17 @@
|
||||||
shareButton.onclick = () => {
|
shareButton.onclick = () => {
|
||||||
let currentProxy = localStorage.getItem("alu__selectedProxy");
|
let currentProxy = localStorage.getItem("alu__selectedProxy");
|
||||||
if (currentProxy && JSON.parse(currentProxy).value === "rammerhead") {
|
if (currentProxy && JSON.parse(currentProxy).value === "rammerhead") {
|
||||||
navigator.clipboard.writeText(window.location.origin + "/" + getCookie("rammerhead-session") + "/" + input!.value.trim());
|
navigator.clipboard.writeText(
|
||||||
|
window.location.origin +
|
||||||
|
"/" +
|
||||||
|
getCookie("rammerhead-session") +
|
||||||
|
"/" +
|
||||||
|
input!.value.trim()
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
navigator.clipboard.writeText(window.__uv$config.decodeUrl(iframe.src.split("/service/")[1]));
|
navigator.clipboard.writeText(
|
||||||
|
window.__uv$config.decodeUrl(iframe.src.split("/service/")[1])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
new Notyf({
|
new Notyf({
|
||||||
duration: 2000,
|
duration: 2000,
|
||||||
|
|
@ -242,11 +258,11 @@
|
||||||
if (!localStorageItem) return "uv";
|
if (!localStorageItem) return "uv";
|
||||||
|
|
||||||
switch (JSON.parse(localStorageItem).value.toLowerCase()) {
|
switch (JSON.parse(localStorageItem).value.toLowerCase()) {
|
||||||
case "ultraviolet":
|
case "ultraviolet":
|
||||||
return "ultraviolet";
|
return "ultraviolet";
|
||||||
case "rammerhead":
|
case "rammerhead":
|
||||||
return "rammerhead";
|
return "rammerhead";
|
||||||
default:
|
default:
|
||||||
return "uv";
|
return "uv";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -265,7 +281,10 @@
|
||||||
proxiedFavicon.src = favicon.href;
|
proxiedFavicon.src = favicon.href;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (proxiedFavicon.src == `${window.location.origin}/custom-favicon?url=${encodedHREF}&contentType=${favicon.type ? encodeURIComponent(favicon.type) : ""}`)
|
if (
|
||||||
|
proxiedFavicon.src ==
|
||||||
|
`${window.location.origin}/custom-favicon?url=${encodedHREF}&contentType=${favicon.type ? encodeURIComponent(favicon.type) : ""}`
|
||||||
|
)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (favicon) {
|
if (favicon) {
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,8 @@ const languageList = [
|
||||||
<Dropdown buttonNameDefault="Alu" dropdownList={themeList} id="dropdown__selected-theme" />
|
<Dropdown buttonNameDefault="Alu" dropdownList={themeList} id="dropdown__selected-theme" />
|
||||||
</div>
|
</div>
|
||||||
<div class="setting__language">
|
<div class="setting__language">
|
||||||
<label aria-label="Language" class="setting-label">{t("settings.customization.language")}</label>
|
<label aria-label="Language" class="setting-label">{t("settings.customization.language")}</label
|
||||||
|
>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
buttonNameDefault="English"
|
buttonNameDefault="English"
|
||||||
dropdownList={languageList}
|
dropdownList={languageList}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,9 @@ const transportsList = [
|
||||||
|
|
||||||
<div class="settings-container">
|
<div class="settings-container">
|
||||||
<div class="setting__selected-proxy">
|
<div class="setting__selected-proxy">
|
||||||
<label aria-label="Selected Proxy" class="setting-label">{t("settings.proxy.selectedProxy")}</label>
|
<label aria-label="Selected Proxy" class="setting-label"
|
||||||
|
>{t("settings.proxy.selectedProxy")}</label
|
||||||
|
>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
buttonNameDefault="Ultraviolet"
|
buttonNameDefault="Ultraviolet"
|
||||||
dropdownList={proxyList}
|
dropdownList={proxyList}
|
||||||
|
|
@ -42,7 +44,9 @@ const transportsList = [
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting__search-engine">
|
<div class="setting__search-engine">
|
||||||
<label aria-label="Search Engine" class="setting-label">{t("settings.proxy.searchEngine")}</label>
|
<label aria-label="Search Engine" class="setting-label"
|
||||||
|
>{t("settings.proxy.searchEngine")}</label
|
||||||
|
>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
buttonNameDefault="Google"
|
buttonNameDefault="Google"
|
||||||
dropdownList={searchEngineList}
|
dropdownList={searchEngineList}
|
||||||
|
|
@ -51,7 +55,9 @@ const transportsList = [
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting__open_with">
|
<div class="setting__open_with">
|
||||||
<label aria-label="Open Page With" class="setting-label">{t("settings.proxy.openPageWith")}</label>
|
<label aria-label="Open Page With" class="setting-label"
|
||||||
|
>{t("settings.proxy.openPageWith")}</label
|
||||||
|
>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
buttonNameDefault={t("settings.proxy.openPageWith.embed")}
|
buttonNameDefault={t("settings.proxy.openPageWith.embed")}
|
||||||
dropdownList={openPageWith}
|
dropdownList={openPageWith}
|
||||||
|
|
@ -60,11 +66,15 @@ const transportsList = [
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting__wisp_url">
|
<div class="setting__wisp_url">
|
||||||
<label aria-label="Wisp URL" for="wisp-url-input" class="setting-label">{t("settings.proxy.wispURL")}</label>
|
<label aria-label="Wisp URL" for="wisp-url-input" class="setting-label"
|
||||||
|
>{t("settings.proxy.wispURL")}</label
|
||||||
|
>
|
||||||
<Input height="50px" inputName="wisp-url" />
|
<Input height="50px" inputName="wisp-url" />
|
||||||
</div>
|
</div>
|
||||||
<div class="setting__bare_url">
|
<div class="setting__bare_url">
|
||||||
<label aria-label="Bare Server URL" for="bare-url-input" class="setting-label">{t("settings.proxy.bareURL")}</label>
|
<label aria-label="Bare Server URL" for="bare-url-input" class="setting-label"
|
||||||
|
>{t("settings.proxy.bareURL")}</label
|
||||||
|
>
|
||||||
<Input height="50px" inputName="bare-url" />
|
<Input height="50px" inputName="bare-url" />
|
||||||
</div>
|
</div>
|
||||||
<div class="setting__transport">
|
<div class="setting__transport">
|
||||||
|
|
@ -78,6 +88,8 @@ const transportsList = [
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting__searxng-url">
|
<div class="setting__searxng-url">
|
||||||
<label aria-label="SearXNG URL" for="searxng-url-input" class="setting-label">{t("settings.proxy.searxngURL")}</label>
|
<label aria-label="SearXNG URL" for="searxng-url-input" class="setting-label"
|
||||||
|
>{t("settings.proxy.searxngURL")}</label
|
||||||
|
>
|
||||||
<Input height="50px" inputName="searxng-url" defaultTextContent="https://searxng.site/" />
|
<Input height="50px" inputName="searxng-url" defaultTextContent="https://searxng.site/" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -68,16 +68,14 @@ export const TransportMgr = new TransportManager();
|
||||||
export async function registerSW() {
|
export async function registerSW() {
|
||||||
navigator.serviceWorker.ready.then(async (sw) => {
|
navigator.serviceWorker.ready.then(async (sw) => {
|
||||||
await registerRemoteListener(sw.active!);
|
await registerRemoteListener(sw.active!);
|
||||||
})
|
});
|
||||||
return new Promise(async (resolve) => {
|
return new Promise(async (resolve) => {
|
||||||
await navigator.serviceWorker
|
await navigator.serviceWorker.register("/sw.js").then((registration) => {
|
||||||
.register("/sw.js")
|
registration.update().then(() => {
|
||||||
.then((registration) => {
|
console.log("Registered SW!");
|
||||||
registration.update().then(() => {
|
resolve(null);
|
||||||
console.log("Registered SW!");
|
|
||||||
resolve(null);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,7 +89,6 @@ export async function initTransport() {
|
||||||
|
|
||||||
export async function loadSelectedTransportScript(): Promise<void> {
|
export async function loadSelectedTransportScript(): Promise<void> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
|
|
||||||
let selectedTransport = localStorage.getItem("alu__selectedTransport");
|
let selectedTransport = localStorage.getItem("alu__selectedTransport");
|
||||||
if (!selectedTransport) {
|
if (!selectedTransport) {
|
||||||
localStorage.setItem("alu__selectedTransport", JSON.stringify({ value: "uv" }));
|
localStorage.setItem("alu__selectedTransport", JSON.stringify({ value: "uv" }));
|
||||||
|
|
|
||||||
|
|
@ -48,11 +48,7 @@ const { title, optionalPreloads } = Astro.props;
|
||||||
/>
|
/>
|
||||||
<meta property="twitter:image" content="/logo.png" />
|
<meta property="twitter:image" content="/logo.png" />
|
||||||
<link rel="sitemap" href="/sitemap-index.xml" />
|
<link rel="sitemap" href="/sitemap-index.xml" />
|
||||||
<link
|
<link href="/varela-round.css" rel="stylesheet" as="style" />
|
||||||
href="/varela-round.css"
|
|
||||||
rel="stylesheet"
|
|
||||||
as="style"
|
|
||||||
/>
|
|
||||||
{
|
{
|
||||||
optionalPreloads?.map((item) => {
|
optionalPreloads?.map((item) => {
|
||||||
return <link rel="preload" href={item.href} as={item.as} />;
|
return <link rel="preload" href={item.href} as={item.as} />;
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,9 @@ export function getStaticPaths() {
|
||||||
<div class="top-bar-left">
|
<div class="top-bar-left">
|
||||||
<button id="close-button">Close</button>
|
<button id="close-button">Close</button>
|
||||||
<div class="nav-container">
|
<div class="nav-container">
|
||||||
<img id="nav-backwards" src="/img/nav/backwards.svg" alt="Backwards Arrow">
|
<img id="nav-backwards" src="/img/nav/backwards.svg" alt="Backwards Arrow" />
|
||||||
<img id="nav-forwards" src="/img/nav/forwards.svg" alt="Forwards Arrow">
|
<img id="nav-forwards" src="/img/nav/forwards.svg" alt="Forwards Arrow" />
|
||||||
<img id="nav-share" src="/img/nav/share.svg" alt="Share Page">
|
<img id="nav-share" src="/img/nav/share.svg" alt="Share Page" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="top-bar-right">
|
<div class="top-bar-right">
|
||||||
|
|
@ -79,7 +79,7 @@ export function getStaticPaths() {
|
||||||
phrase: string;
|
phrase: string;
|
||||||
};
|
};
|
||||||
await registerSW();
|
await registerSW();
|
||||||
|
|
||||||
async function sendAPIRequest(urlInput: HTMLInputElement, searchSuggestions: HTMLDivElement) {
|
async function sendAPIRequest(urlInput: HTMLInputElement, searchSuggestions: HTMLDivElement) {
|
||||||
if (!urlInput) throw new Error("urlInput is null");
|
if (!urlInput) throw new Error("urlInput is null");
|
||||||
if (!searchSuggestions) throw new Error("searchSuggestions is null");
|
if (!searchSuggestions) throw new Error("searchSuggestions is null");
|
||||||
|
|
@ -108,7 +108,7 @@ export function getStaticPaths() {
|
||||||
searchSuggestions.style.opacity = "1";
|
searchSuggestions.style.opacity = "1";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addEventListeners() {
|
function addEventListeners() {
|
||||||
let urlInput = document.getElementById("url-input") as HTMLInputElement;
|
let urlInput = document.getElementById("url-input") as HTMLInputElement;
|
||||||
let searchSuggestions = document.getElementById("search-suggestions") as HTMLDivElement;
|
let searchSuggestions = document.getElementById("search-suggestions") as HTMLDivElement;
|
||||||
|
|
@ -131,7 +131,7 @@ export function getStaticPaths() {
|
||||||
}, 200);
|
}, 200);
|
||||||
urlInput.classList.remove("search-results");
|
urlInput.classList.remove("search-results");
|
||||||
});
|
});
|
||||||
|
|
||||||
urlInput.addEventListener("keyup", async () => {
|
urlInput.addEventListener("keyup", async () => {
|
||||||
if (urlInput.value.length >= 3) {
|
if (urlInput.value.length >= 3) {
|
||||||
return await sendAPIRequest(urlInput, searchSuggestions);
|
return await sendAPIRequest(urlInput, searchSuggestions);
|
||||||
|
|
@ -144,7 +144,6 @@ export function getStaticPaths() {
|
||||||
</script>
|
</script>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
|
|
||||||
<style is:global>
|
<style is:global>
|
||||||
#main-content {
|
#main-content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ export function getStaticPaths() {
|
||||||
<CreditsTab />
|
<CreditsTab />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="popup">
|
<div class="popup">
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<input type="radio" id="setting-tab-proxy" class="setting-tab" name="tab" checked="true" />
|
<input type="radio" id="setting-tab-proxy" class="setting-tab" name="tab" checked="true" />
|
||||||
|
|
@ -70,12 +70,12 @@ export function getStaticPaths() {
|
||||||
window.loadedContentStorage[tab.id] = contentToLoad.innerHTML;
|
window.loadedContentStorage[tab.id] = contentToLoad.innerHTML;
|
||||||
contentToLoad.remove();
|
contentToLoad.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
tab.addEventListener("click", (event) => {
|
tab.addEventListener("click", (event) => {
|
||||||
loadContent(event.target.id);
|
loadContent(event.target.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function loadContent(tabID) {
|
function loadContent(tabID) {
|
||||||
if (window.currentlySelectedTab == tabID) return;
|
if (window.currentlySelectedTab == tabID) return;
|
||||||
else window.currentlySelectedTab = tabID;
|
else window.currentlySelectedTab = tabID;
|
||||||
|
|
@ -90,7 +90,7 @@ export function getStaticPaths() {
|
||||||
}, 250);
|
}, 250);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addDropdownListener() {
|
function addDropdownListener() {
|
||||||
let dropdown_toggles = document.getElementsByClassName("dropdown-toggle");
|
let dropdown_toggles = document.getElementsByClassName("dropdown-toggle");
|
||||||
Array.from(dropdown_toggles).forEach((toggle) => {
|
Array.from(dropdown_toggles).forEach((toggle) => {
|
||||||
|
|
@ -100,7 +100,7 @@ export function getStaticPaths() {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleDropdown(toggle) {
|
function toggleDropdown(toggle) {
|
||||||
let dropdown = document.getElementById(toggle.id + "-menu");
|
let dropdown = document.getElementById(toggle.id + "-menu");
|
||||||
if (dropdown.style.maxHeight == "0px" || dropdown.style.maxHeight == "") {
|
if (dropdown.style.maxHeight == "0px" || dropdown.style.maxHeight == "") {
|
||||||
|
|
@ -113,7 +113,7 @@ export function getStaticPaths() {
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function determineListener(event) {
|
function determineListener(event) {
|
||||||
if (event.detail == "setting-tab-proxy") {
|
if (event.detail == "setting-tab-proxy") {
|
||||||
addDropdownListener();
|
addDropdownListener();
|
||||||
|
|
@ -121,7 +121,7 @@ export function getStaticPaths() {
|
||||||
addDropdownListener();
|
addDropdownListener();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeOtherDropdowns(dropdownIDToExclude) {
|
function closeOtherDropdowns(dropdownIDToExclude) {
|
||||||
let dropdowns = document.getElementsByClassName("dropdown-menu");
|
let dropdowns = document.getElementsByClassName("dropdown-menu");
|
||||||
Array.from(dropdowns).forEach((dropdown) => {
|
Array.from(dropdowns).forEach((dropdown) => {
|
||||||
|
|
@ -134,7 +134,7 @@ export function getStaticPaths() {
|
||||||
}, 300);
|
}, 300);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeDropdown(dropdownID) {
|
function closeDropdown(dropdownID) {
|
||||||
let dropdown = document.getElementById(dropdownID);
|
let dropdown = document.getElementById(dropdownID);
|
||||||
if (dropdown) {
|
if (dropdown) {
|
||||||
|
|
@ -145,12 +145,12 @@ export function getStaticPaths() {
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLocalStorageValue(localStorageItem, dropdownID) {
|
function getLocalStorageValue(localStorageItem, dropdownID) {
|
||||||
// I was kinda dumb for not doing this earlier.
|
// I was kinda dumb for not doing this earlier.
|
||||||
let dropdown = document.getElementById(dropdownID);
|
let dropdown = document.getElementById(dropdownID);
|
||||||
let dropdownMenu = document.getElementById(dropdownID + "-menu");
|
let dropdownMenu = document.getElementById(dropdownID + "-menu");
|
||||||
|
|
||||||
if (dropdown && dropdownMenu) {
|
if (dropdown && dropdownMenu) {
|
||||||
// Now we find the child that matches localStorageItem.value.
|
// Now we find the child that matches localStorageItem.value.
|
||||||
let dropdownItem = Array.from(dropdownMenu.children).find((item) => {
|
let dropdownItem = Array.from(dropdownMenu.children).find((item) => {
|
||||||
|
|
@ -160,7 +160,7 @@ export function getStaticPaths() {
|
||||||
return dropdownItem.innerText;
|
return dropdownItem.innerText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function applySavedLocalStorage(localStorageItem, dropdownID) {
|
function applySavedLocalStorage(localStorageItem, dropdownID) {
|
||||||
if (localStorage.getItem(localStorageItem)) {
|
if (localStorage.getItem(localStorageItem)) {
|
||||||
let dropdown_toggle = document.getElementById(dropdownID);
|
let dropdown_toggle = document.getElementById(dropdownID);
|
||||||
|
|
@ -169,7 +169,7 @@ export function getStaticPaths() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyDropdownEventListeners(item, dropdownID, localStorageItem, optionalCallback) {
|
function applyDropdownEventListeners(item, dropdownID, localStorageItem, optionalCallback) {
|
||||||
Array.from(item.children).forEach((item) => {
|
Array.from(item.children).forEach((item) => {
|
||||||
item.onclick = () => {
|
item.onclick = () => {
|
||||||
|
|
@ -186,17 +186,17 @@ export function getStaticPaths() {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyInputListeners(item, localStorageItem) {
|
function applyInputListeners(item, localStorageItem) {
|
||||||
item.addEventListener("input", () => {
|
item.addEventListener("input", () => {
|
||||||
localStorage.setItem(localStorageItem, item.value);
|
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() {
|
function setupCustomizationSettings() {
|
||||||
applySavedLocalStorage("alu__selectedTheme", "dropdown__selected-theme");
|
applySavedLocalStorage("alu__selectedTheme", "dropdown__selected-theme");
|
||||||
applySavedLocalStorage("alu__selectedLanguage", "dropdown__selected-language");
|
applySavedLocalStorage("alu__selectedLanguage", "dropdown__selected-language");
|
||||||
|
|
@ -215,20 +215,20 @@ export function getStaticPaths() {
|
||||||
navigateToNewLangaugePage
|
navigateToNewLangaugePage
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupCloakingSettings() {
|
function setupCloakingSettings() {
|
||||||
Array.from(document.getElementById("cloak-list").children).forEach((cloak) => {
|
Array.from(document.getElementById("cloak-list").children).forEach((cloak) => {
|
||||||
cloak.addEventListener("click", () => {
|
cloak.addEventListener("click", () => {
|
||||||
let cloakName = cloak.dataset.cloakName;
|
let cloakName = cloak.dataset.cloakName;
|
||||||
let cloakIcon = cloak.dataset.cloakIcon;
|
let cloakIcon = cloak.dataset.cloakIcon;
|
||||||
|
|
||||||
let localStorageItem = {
|
let localStorageItem = {
|
||||||
name: cloakName,
|
name: cloakName,
|
||||||
icon: cloakIcon,
|
icon: cloakIcon,
|
||||||
isCustom: false,
|
isCustom: false,
|
||||||
};
|
};
|
||||||
localStorage.setItem("alu__selectedCloak", JSON.stringify(localStorageItem));
|
localStorage.setItem("alu__selectedCloak", JSON.stringify(localStorageItem));
|
||||||
|
|
||||||
if (cloakName == "None") {
|
if (cloakName == "None") {
|
||||||
localStorage.removeItem("alu__selectedCloak");
|
localStorage.removeItem("alu__selectedCloak");
|
||||||
cloakName = "Settings | Alu";
|
cloakName = "Settings | Alu";
|
||||||
|
|
@ -242,7 +242,7 @@ export function getStaticPaths() {
|
||||||
}
|
}
|
||||||
link.href = cloakIcon;
|
link.href = cloakIcon;
|
||||||
document.title = cloakName;
|
document.title = cloakName;
|
||||||
|
|
||||||
if (!cloak.classList.contains("selected")) {
|
if (!cloak.classList.contains("selected")) {
|
||||||
Array.from(document.getElementById("cloak-list").children).forEach((cloak2) => {
|
Array.from(document.getElementById("cloak-list").children).forEach((cloak2) => {
|
||||||
cloak2.classList.remove("selected");
|
cloak2.classList.remove("selected");
|
||||||
|
|
@ -251,7 +251,7 @@ export function getStaticPaths() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let customNameInput = document.getElementById("cloak-custom-name-input");
|
let customNameInput = document.getElementById("cloak-custom-name-input");
|
||||||
let customFaviconInput = document.getElementById("cloak-custom-favicon-input");
|
let customFaviconInput = document.getElementById("cloak-custom-favicon-input");
|
||||||
if (localStorage.getItem("alu__selectedCloak")) {
|
if (localStorage.getItem("alu__selectedCloak")) {
|
||||||
|
|
@ -261,7 +261,7 @@ export function getStaticPaths() {
|
||||||
customFaviconInput.value = selectedCloak.icon;
|
customFaviconInput.value = selectedCloak.icon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById("cloak-custom-button").addEventListener("click", () => {
|
document.getElementById("cloak-custom-button").addEventListener("click", () => {
|
||||||
let cloakName = document.getElementById("cloak-custom-name-input").value;
|
let cloakName = document.getElementById("cloak-custom-name-input").value;
|
||||||
let cloakIcon = document.getElementById("cloak-custom-favicon-input").value;
|
let cloakIcon = document.getElementById("cloak-custom-favicon-input").value;
|
||||||
|
|
@ -286,7 +286,7 @@ export function getStaticPaths() {
|
||||||
document.title = cloakName;
|
document.title = cloakName;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeTheme() {
|
function changeTheme() {
|
||||||
let theme = JSON.parse(localStorage.getItem("alu__selectedTheme")).value;
|
let theme = JSON.parse(localStorage.getItem("alu__selectedTheme")).value;
|
||||||
if (theme) {
|
if (theme) {
|
||||||
|
|
@ -297,7 +297,7 @@ export function getStaticPaths() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupSettings(event) {
|
function setupSettings(event) {
|
||||||
if (event.detail == "setting-tab-proxy") {
|
if (event.detail == "setting-tab-proxy") {
|
||||||
applySavedLocalStorage("alu__selectedProxy", "dropdown__selected-proxy");
|
applySavedLocalStorage("alu__selectedProxy", "dropdown__selected-proxy");
|
||||||
|
|
@ -323,22 +323,25 @@ export function getStaticPaths() {
|
||||||
if (savedWispUrl == null || savedWispUrl == "")
|
if (savedWispUrl == null || savedWispUrl == "")
|
||||||
localStorage.setItem("alu__wispUrl", webSocketProtocol + location.host + "/wisp/");
|
localStorage.setItem("alu__wispUrl", webSocketProtocol + location.host + "/wisp/");
|
||||||
let savedBareUrl = localStorage.getItem("alu__bareUrl");
|
let savedBareUrl = localStorage.getItem("alu__bareUrl");
|
||||||
if (savedBareUrl == null || savedBareUrl == "") localStorage.setItem("alu__bareUrl", location.origin + "/bare/");
|
if (savedBareUrl == null || savedBareUrl == "")
|
||||||
|
localStorage.setItem("alu__bareUrl", location.origin + "/bare/");
|
||||||
wispURLInput.value = localStorage.getItem("alu__wispUrl");
|
wispURLInput.value = localStorage.getItem("alu__wispUrl");
|
||||||
bareURLInput.value = localStorage.getItem("alu__bareUrl");
|
bareURLInput.value = localStorage.getItem("alu__bareUrl");
|
||||||
// Proxy settings
|
// Proxy settings
|
||||||
applyInputListeners(searxngUrlInput, "alu__searxngUrl");
|
applyInputListeners(searxngUrlInput, "alu__searxngUrl");
|
||||||
applyInputListeners(wispURLInput, "alu__wispUrl");
|
applyInputListeners(wispURLInput, "alu__wispUrl");
|
||||||
applyInputListeners(bareURLInput, "alu__bareUrl");
|
applyInputListeners(bareURLInput, "alu__bareUrl");
|
||||||
|
|
||||||
[selectedProxyDropdown, openWithDropdown, currentTransportDropdown].forEach((dropdown) => {
|
[selectedProxyDropdown, openWithDropdown, currentTransportDropdown].forEach(
|
||||||
let dropdownButton = document.getElementById(dropdown.id.replace("-menu", ""));
|
(dropdown) => {
|
||||||
applyDropdownEventListeners(
|
let dropdownButton = document.getElementById(dropdown.id.replace("-menu", ""));
|
||||||
dropdown,
|
applyDropdownEventListeners(
|
||||||
dropdownButton.id,
|
dropdown,
|
||||||
dropdownButton.dataset.localStorageKey
|
dropdownButton.id,
|
||||||
);
|
dropdownButton.dataset.localStorageKey
|
||||||
});
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
applyDropdownEventListeners(
|
applyDropdownEventListeners(
|
||||||
searchEngineDropdown,
|
searchEngineDropdown,
|
||||||
"dropdown__search-engine",
|
"dropdown__search-engine",
|
||||||
|
|
@ -352,7 +355,7 @@ export function getStaticPaths() {
|
||||||
setupCloakingSettings();
|
setupCloakingSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkSearxng() {
|
function checkSearxng() {
|
||||||
// This function checks if the "searxng" option was clicked, display an additional option if so.
|
// This function checks if the "searxng" option was clicked, display an additional option if so.
|
||||||
let search_engine = JSON.parse(localStorage.getItem("alu__search_engine"));
|
let search_engine = JSON.parse(localStorage.getItem("alu__search_engine"));
|
||||||
|
|
@ -364,9 +367,9 @@ export function getStaticPaths() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("setting-tabLoad", setupSettings);
|
document.addEventListener("setting-tabLoad", setupSettings);
|
||||||
|
|
||||||
function navigateToNewLangaugePage() {
|
function navigateToNewLangaugePage() {
|
||||||
let value = JSON.parse(localStorage.getItem("alu__selectedLanguage")).value;
|
let value = JSON.parse(localStorage.getItem("alu__selectedLanguage")).value;
|
||||||
let currentLanguage = window.location.pathname.split("/")[1];
|
let currentLanguage = window.location.pathname.split("/")[1];
|
||||||
|
|
@ -414,7 +417,7 @@ export function getStaticPaths() {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
color: var(--text-color-accent);
|
color: var(--text-color-accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.setting-label {
|
.setting-label {
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
|
@ -429,7 +432,7 @@ export function getStaticPaths() {
|
||||||
cursor: auto;
|
cursor: auto;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.setting__searxng-url {
|
.setting__searxng-url {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
@ -553,5 +556,3 @@ export function getStaticPaths() {
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ import { ViewTransitions } from "astro:transitions";
|
||||||
<ViewTransitions />
|
<ViewTransitions />
|
||||||
<script>
|
<script>
|
||||||
let currentLang = localStorage.getItem("alu__selectedLanguage");
|
let currentLang = localStorage.getItem("alu__selectedLanguage");
|
||||||
const redirect = (loc: string) => window.location.href = loc
|
const redirect = (loc: string) => (window.location.href = loc);
|
||||||
if (currentLang) {
|
if (currentLang) {
|
||||||
try {
|
try {
|
||||||
let parsed = JSON.parse(currentLang).value;
|
let parsed = JSON.parse(currentLang).value;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue