Revela-v4/src/pages/[lang]/settings.astro

539 lines
18 KiB
Text

---
import ProxyTab from "@components/SettingsContent/ProxyTab.astro";
import CustomizationTab from "@components/SettingsContent/CustomizationTab.astro";
import CloakingTab from "@components/SettingsContent/CloakingTab.astro";
import CreditsTab from "@components/SettingsContent/CreditsTab.astro";
import Layout from "src/layouts/Layout.astro";
import { STATIC_PATHS, i18n } from "@i18n/utils";
const lang = i18n.getLangFromUrl(Astro.url);
const t = i18n.useTranslations(lang);
export function getStaticPaths() {
return STATIC_PATHS;
}
---
<Layout title={t("pages.settings")}>
<main id="main-content">
<h1 class="title-text">{t("settings.title")}</h1>
<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>
<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>
</div>
</main>
<script is:inline>
Alu.settings.contentStore = {};
Alu.settings.currentPage;
function settingsLoad() {
document.addEventListener("astro:before-swap", () => {
Alu.settings.currentPage = "";
});
Array.from(document.getElementsByClassName("setting-tab")).forEach((tab) => {
const contentToLoad = document.getElementById("content-" + tab.id);
if (contentToLoad) {
Alu.settings.contentStore[tab.id] = contentToLoad.innerHTML;
contentToLoad.remove();
}
tab.addEventListener("click", (event) => {
loadContent(event.target.id);
});
});
}
function loadContent(tabID) {
let curTabID = Alu.settings.currentPage
if (curTabID == tabID) return;
else curTabID = tabID;
const currentContent = document.getElementById("current-content");
if (currentContent) {
currentContent.style.opacity = "0";
setTimeout(() => {
currentContent.innerHTML = Alu.settings.contentStore[tabID];
currentContent.style.opacity = "1";
document.dispatchEvent(new CustomEvent("setting-tabLoad", { detail: tabID }));
}, 250);
}
}
function addDropdownListener() {
const dropdown_toggles = document.getElementsByClassName("dropdown-toggle");
Array.from(dropdown_toggles).forEach((toggle) => {
toggle.onclick = function () {
closeOtherDropdowns(toggle.id);
toggleDropdown(toggle);
};
});
}
function toggleDropdown(toggle) {
const dropdown = document.getElementById(toggle.id + "-menu");
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 closeOtherDropdowns(dropdownIDToExclude) {
const dropdowns = document.getElementsByClassName("dropdown-menu");
Array.from(dropdowns).forEach((dropdown) => {
dropdown.style.maxHeight = "0px";
setTimeout(() => {
if (dropdown.id != dropdownIDToExclude + "-menu") {
const dropdown_toggle = document.getElementById(dropdown.id.replace("-menu", ""));
dropdown_toggle.style.borderRadius = "10px";
}
}, 300);
});
}
function closeDropdown(dropdownID) {
const dropdown = document.getElementById(dropdownID);
if (dropdown) {
dropdown.style.maxHeight = "0px";
setTimeout(() => {
const 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.
const dropdown = document.getElementById(dropdownID);
const dropdownMenu = document.getElementById(dropdownID + "-menu");
if (dropdown && dropdownMenu) {
// Now we find the child that matches localStorageItem.value.
const dropdownItem = Array.from(dropdownMenu.children).find((item) => {
return Alu.store.get(localStorageItem).value == item.dataset.setting;
});
// Now set the inner text to the name in the dropdownItem.
return dropdownItem.innerText;
}
}
function applySavedLocalStorage(localStorageItem, dropdownID) {
if (Alu.store.get(localStorageItem)) {
const dropdown_toggle = document.getElementById(dropdownID);
if (dropdown_toggle) {
dropdown_toggle.innerText = getLocalStorageValue(localStorageItem, dropdownID);
}
}
}
function applyDropdownEventListeners(dropdown, optionalCallback) {
const dropdownSibling = document.getElementById(dropdown.id + "-menu");
const localStorageItem = dropdown.dataset.localStorageKey;
Array.from(dropdownSibling.children).forEach((child) => {
child.onclick = () => {
const localStorageItemContent = {
name: child.innerText,
value: child.dataset.setting,
};
Alu.store.set(localStorageItem, localStorageItemContent);
applySavedLocalStorage(localStorageItem, dropdown.id);
closeDropdown(dropdownSibling.id);
if (typeof optionalCallback == "function") {
optionalCallback();
}
};
});
}
function applyInputListeners(item, localStorageItem) {
item.addEventListener("input", () => {
Alu.store.set(localStorageItem, { value: item.value });
});
}
function addThemeToDropdown(extension) {
const dropdown = document.getElementById("dropdown__selected-theme-menu");
if (dropdown) {
// TODO: Figure out why addThemeToDropdown is being called 6 times
// This when you go from another page and back to settings->customization.
const duplicateItem = Array.from(dropdown.children).find((item) => {
return item.dataset.setting == extension.themeName;
});
if (duplicateItem) return;
const themeItem = document.createElement("li");
themeItem.classList.add("dropdown-item");
themeItem.dataset.setting = extension.themeName;
themeItem.textContent = extension.title;
dropdown.appendChild(themeItem);
}
}
document.addEventListener("setting-tabLoad", determineListener);
loadContent("setting-tab-proxy");
function setupCustomizationSettings() {
const store = window.idb.transaction("InstalledExtensions", "readonly").objectStore("InstalledExtensions");
store.getAll().onsuccess = (event) => {
const result = event.target.result;
if (result) {
result.forEach((extension) => {
if (extension.type === "theme" && extension.themeName) {
// Create a dropdown item for the theme
addThemeToDropdown(extension);
}
});
}
applySavedLocalStorage("theme", "dropdown__selected-theme");
applySavedLocalStorage("lang", "dropdown__selected-language");
const themeDropdown = document.getElementById("dropdown__selected-theme");
const languageDropdown = document.getElementById("dropdown__selected-language");
applyDropdownEventListeners(themeDropdown, changeTheme);
applyDropdownEventListeners(languageDropdown, 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;
const cloakItem = {
name: cloakName,
icon: cloakIcon,
isCustom: false,
};
Alu.store.set("cloak", cloakItem);
if (cloakName == "None") {
Alu.store.remove("cloak");
cloakName = "Settings | Alu";
cloakIcon = "/favicon.svg";
}
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");
}
});
});
const customNameInput = document.getElementById("cloak-custom-name-input");
const customFaviconInput = document.getElementById("cloak-custom-favicon-input");
const cloak = Alu.store.get("cloak");
if (cloak) {
if (cloak.isCustom) {
customNameInput.value = cloak.name;
customFaviconInput.value = cloak.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;
const cloakItem = {
name: cloakName,
icon: cloakIcon,
isCustom: true,
};
Alu.store.set("cloak", cloakItem);
if (cloakName == "None") {
Alu.store.remove("cloak");
cloakName = "Settings | Alu";
cloakIcon = "/favicon.svg";
}
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 changeTheme() {
const theme = Alu.store.get("theme").value;
document.documentElement.setAttribute("data-theme", theme);
}
function setupSettings(event) {
if (event.detail == "setting-tab-proxy") {
applySavedLocalStorage("proxy", "dropdown__selected-proxy");
applySavedLocalStorage("search", "dropdown__search-engine");
applySavedLocalStorage("openpage", "dropdown__open-with");
applySavedLocalStorage("wisp", "dropdown__wisp-url");
applySavedLocalStorage("transport", "dropdown__transport");
// Dropdowns
const selectedProxyDropdown = document.getElementById("dropdown__selected-proxy");
const searchEngineDropdown = document.getElementById("dropdown__search-engine");
const openWithDropdown = document.getElementById("dropdown__open-with");
const currentTransportDropdown = document.getElementById("dropdown__transport");
const wispURLDropdown = document.getElementById("dropdown__wisp-url");
// Inputs
const searxngUrlInput = document.getElementById("searxng-url-input");
const bareURLInput = document.getElementById("bare-url-input");
bareURLInput.value = Alu.store.get("bareUrl").value;
// Proxy settings
[selectedProxyDropdown, openWithDropdown, currentTransportDropdown, wispURLDropdown].forEach((dropdown) => {
applyDropdownEventListeners(dropdown);
});
applyDropdownEventListeners(searchEngineDropdown, checkSearxng);
checkSearxng();
applyInputListeners(searxngUrlInput, "searxng");
applyInputListeners(bareURLInput, "bareUrl");
} else if (event.detail == "setting-tab-customization") {
setupCustomizationSettings();
} else if (event.detail == "setting-tab-cloaking") {
setupCloakingSettings();
}
}
function checkSearxng() {
// Callback for search engine dropdown
const searchEngine = Alu.store.get("search");
if (searchEngine.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() {
const value = Alu.store.get("lang").value;
const currentLanguage = window.location.pathname.split("/")[1];
if (value == currentLanguage) return;
window.location.href = `/${value}/settings`;
}
document.addEventListener("astro:after-swap", () => {
setTimeout(() => {
settingsLoad();
}, 200);
});
settingsLoad();
</script>
<style is:global>
.content-hidden {
display: none;
}
#current-content {
transition: opacity 250ms ease-in-out;
margin-left: 20px;
height: 700px;
}
.settings-container {
display: flex;
gap: 20px;
position: relative;
z-index: 2;
flex-wrap: wrap;
row-gap: 5px;
}
.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;
margin-block: 1em;
margin-inline: 0;
user-select: none;
width: 100%;
cursor: auto;
margin-bottom: 5px;
}
.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;
max-height: 500px;
border-radius: 15px;
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: 40px;
}
@media (max-width: 1116px) {
.popup {
flex-direction: column;
min-height: 80%;
max-height: 80%;
}
.tabs {
flex-direction: row;
max-width: 100%;
max-height: 70px;
min-height: 70px;
gap: 0;
align-items: center;
}
label {
width: auto;
margin-left: 0;
}
}
@media (max-width: 500px) {
label {
font-size: 20px;
}
}
@media (max-width: 375px) {
label {
font-size: 18px;
}
}
.setting {
width: 140px;
}
.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;
}
@media (min-width: 1116px) {
#setting-tab-proxy:checked ~ .marker {
transform: translateY(0%);
}
#setting-tab-customization:checked ~ .marker {
transform: translateY(14%);
}
#setting-tab-cloaking:checked ~ .marker {
transform: translateY(28%);
}
#setting-tab-credits:checked ~ .marker {
transform: translateY(42.5%);
}
}
</style>
</Layout>