Rename mocha and macchiato i18n key to just catppuccin, only add eng translation. Move settings code to settings.ts, and fix links in credits page.
This commit is contained in:
parent
e0a8eb0dd4
commit
26797b6ee6
13 changed files with 383 additions and 365 deletions
|
|
@ -1,39 +1,38 @@
|
|||
---
|
||||
import Card from "@components/UI/Card.astro";
|
||||
import Link from "@components/UI/Link.astro";
|
||||
import { i18n } from "@i18n/utils";
|
||||
const t = i18n.inferLangUseTranslations(Astro.url);
|
||||
---
|
||||
|
||||
<div class="settings-container">
|
||||
<div class="credits-container">
|
||||
<Card title={t("ultraviolet")}>
|
||||
<Link href="https://titaniumnetwork.org/" newTab>Titanium Network</Link>
|
||||
<Card title={t("ultraviolet")} href="https://titaniumnetwork.org">
|
||||
Titanium Network
|
||||
</Card>
|
||||
<Card title={t("settings.credits.esTranslations")}>
|
||||
<Link href="https://github.com/builtbyvys/" newTab>vys</Link>
|
||||
<Card title={t("settings.credits.esTranslations")} href="https://github.com/builtbyvys/">
|
||||
vys
|
||||
</Card>
|
||||
<Card title={t("settings.credits.frTranslations")}>
|
||||
<Link href="https://github.com/notboeing747">notboeing747</Link>
|
||||
<Card title={t("settings.credits.frTranslations")} href="https://github.com/notboeing747">
|
||||
notboeing747
|
||||
</Card>
|
||||
<Card title={t("settings.credits.jpTranslations")}>
|
||||
<Link href="https://wearr.dev" newTab>wearr</Link>
|
||||
<Card title={t("settings.credits.jpTranslations")} href="https://wearr.dev">
|
||||
wearr
|
||||
</Card>
|
||||
<Card title={t("settings.credits.ptTranslations")}> kersosina_ </Card>
|
||||
<Card title={t("settings.credits.ruTranslations")}>
|
||||
<Link href="https://3kh0.net" newTab>Echo</Link>
|
||||
<Card title={t("settings.credits.ruTranslations")} href="https://3kh0.net">
|
||||
Echo
|
||||
</Card>
|
||||
<Card title={t("settings.credits.zhTranslations")}>
|
||||
<Link href="https://3kh0.net" newTab>Echo</Link>
|
||||
<Card title={t("settings.credits.zhTranslations")} href="https://3kh0.net">
|
||||
Echo
|
||||
</Card>
|
||||
<Card title={t("settings.credits.mochaandmacchiatothemes")}>
|
||||
<Link href="https://github.com/catppuccin/catppuccin" newTab>Catppuccin</Link>
|
||||
<Card title={t("settings.credits.catppuccin")} href="https://github.com/catppuccin/catppuccin">
|
||||
Catppuccin
|
||||
</Card>
|
||||
<Card title="Wisp Server">
|
||||
<Link href="https://github.com/MercuryWorkshop/wisp-server-node" newTab>Wisp Server</Link>
|
||||
<Card title="Wisp Server" href="https://github.com/MercuryWorkshop/wisp-server-node">
|
||||
Mercury Workshop
|
||||
</Card>
|
||||
<Card title="Rosé Pine Theme">
|
||||
<Link href="https://rosepinetheme.com/" newTab>Rosé Pine</Link>
|
||||
<Card title="Rosé Pine Theme" href="https://rosepinetheme.com/">
|
||||
Rosé Pine
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,31 @@
|
|||
---
|
||||
const { title } = Astro.props;
|
||||
import Link from './Link.astro';
|
||||
|
||||
const { title, href } = Astro.props;
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
href?: string;
|
||||
}
|
||||
|
||||
const ID = title.toLowerCase().replaceAll(" ", "-");
|
||||
---
|
||||
|
||||
<div class="card" id=`card-${title.toLowerCase()}`>
|
||||
<h2 class="card-title">{title}</h2>
|
||||
<slot />
|
||||
</div>
|
||||
{href ? (
|
||||
<Link href={href} newTab>
|
||||
<div class="card card-link" id={"card-" + ID}>
|
||||
<h2 class="card-title">{title}</h2>
|
||||
<slot />
|
||||
</div>
|
||||
</Link>
|
||||
) : (
|
||||
<div class="card" id={"card-" + ID}>
|
||||
<h2 class="card-title">{title}</h2>
|
||||
<slot />
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
.card {
|
||||
|
|
@ -21,10 +37,12 @@ interface Props {
|
|||
background-color: var(--background-highlight);
|
||||
border-radius: 10px;
|
||||
padding-bottom: 1rem;
|
||||
transition: 250ms ease-in-out;
|
||||
cursor: pointer;
|
||||
}
|
||||
.card:hover {
|
||||
.card-link {
|
||||
cursor: pointer;
|
||||
transition: 250ms ease-in-out;
|
||||
}
|
||||
.card-link:hover {
|
||||
filter: brightness(0.8);
|
||||
}
|
||||
.card-title {
|
||||
|
|
|
|||
|
|
@ -10,11 +10,12 @@ const target = newTab ? "_blank" : "_self";
|
|||
const rel = newTab ? "noopener noreferrer" : "";
|
||||
---
|
||||
|
||||
<a href={href} target={target} rel={rel}><slot /></a>
|
||||
<a href={href} target={target} rel={rel}>
|
||||
<slot />
|
||||
</a>
|
||||
|
||||
<style>
|
||||
a {
|
||||
color: var(--text-color);
|
||||
width: fit-content;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const KEYSTORE: Alu.DefaultKeys = {
|
||||
proxy: {
|
||||
name: "Ultraviolet",
|
||||
value: "ultraviolet",
|
||||
name: "Auto",
|
||||
value: "auto",
|
||||
},
|
||||
search: {
|
||||
name: "Google",
|
||||
|
|
@ -36,33 +36,33 @@ if (localStorage.getItem("AluStore") === null) {
|
|||
}
|
||||
|
||||
class AluStore {
|
||||
private store: Alu.DefaultKeys;
|
||||
#store: Alu.DefaultKeys;
|
||||
constructor() {
|
||||
const localstore = localStorage.getItem("AluStore");
|
||||
if (!localstore) {
|
||||
localStorage.setItem("AluStore", JSON.stringify(KEYSTORE));
|
||||
}
|
||||
this.store = JSON.parse(localStorage.getItem("AluStore") || "{}");
|
||||
this.#store = JSON.parse(localStorage.getItem("AluStore") || "{}");
|
||||
}
|
||||
public getStore(): Alu.DefaultKeys {
|
||||
return this.store;
|
||||
return this.#store;
|
||||
}
|
||||
public get(key: Alu.ValidStoreKeys): Alu.Key {
|
||||
return this.store[key];
|
||||
return this.#store[key];
|
||||
}
|
||||
public set(key: Alu.ValidStoreKeys, value: Alu.Key): void {
|
||||
this.store[key] = value;
|
||||
this.#store[key] = value;
|
||||
this.save();
|
||||
}
|
||||
public reset(key: Alu.ValidStoreKeys) {
|
||||
this.set(key, KEYSTORE[key]);
|
||||
}
|
||||
public remove(key: Alu.ValidStoreKeys) {
|
||||
delete this.store[key];
|
||||
delete this.#store[key];
|
||||
this.save();
|
||||
}
|
||||
private save(): void {
|
||||
localStorage.setItem("AluStore", JSON.stringify(this.store));
|
||||
localStorage.setItem("AluStore", JSON.stringify(this.#store));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
324
src/components/ts/settings.ts
Normal file
324
src/components/ts/settings.ts
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
window.loadedContentStorage = {};
|
||||
window.currentlySelectedTab;
|
||||
document.addEventListener("astro:before-swap", () => {
|
||||
window.currentlySelectedTab = "";
|
||||
});
|
||||
function settingsLoad() {
|
||||
Array.from(document.getElementsByClassName("setting-tab")).forEach((tab) => {
|
||||
const contentToLoad = document.getElementById("content-" + tab.id);
|
||||
if (contentToLoad) {
|
||||
window.loadedContentStorage[tab.id] = contentToLoad.innerHTML;
|
||||
contentToLoad.remove();
|
||||
}
|
||||
|
||||
tab.addEventListener("click", (event: Event) => {
|
||||
const target = event.target as HTMLElement;
|
||||
loadContent(target.id);
|
||||
});
|
||||
});
|
||||
}
|
||||
function loadContent(tabID: string) {
|
||||
if (window.currentlySelectedTab == tabID) return;
|
||||
else window.currentlySelectedTab = tabID;
|
||||
const 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-tabLoad", { detail: tabID }));
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
|
||||
function addDropdownListener() {
|
||||
const dropdown_toggles = document.getElementsByClassName("dropdown-toggle") as HTMLCollectionOf<HTMLElement>;
|
||||
Array.from(dropdown_toggles).forEach((toggle) => {
|
||||
toggle.onclick = function () {
|
||||
closeOtherDropdowns(toggle.id);
|
||||
toggleDropdown(toggle);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function toggleDropdown(toggle: HTMLElement) {
|
||||
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 closeOtherDropdowns(dropdownIDToExclude: string) {
|
||||
const dropdowns = document.getElementsByClassName("dropdown-menu") as HTMLCollectionOf<HTMLElement>;
|
||||
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: string) {
|
||||
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: Alu.ValidStoreKeys, dropdownID: string) {
|
||||
// I was kinda dumb for not doing this earlier.
|
||||
const dropdown = document.getElementById(dropdownID);
|
||||
const dropdownMenu = document.getElementById(dropdownID + "-menu") as HTMLElement;
|
||||
|
||||
if (dropdown && dropdownMenu) {
|
||||
// Now we find the child that matches localStorageItem.value.
|
||||
const dropdownItem = Array.from(dropdownMenu.children).find((item) => {
|
||||
const itemEl = item as HTMLElement;
|
||||
return Alu.store.get(localStorageItem).value == itemEl.dataset.setting;
|
||||
}) as HTMLElement;
|
||||
// Now set the inner text to the name in the dropdownItem.
|
||||
return dropdownItem.innerText;
|
||||
}
|
||||
}
|
||||
|
||||
function applySavedLocalStorage(localStorageItem: Alu.ValidStoreKeys, dropdownID: string) {
|
||||
if (Alu.store.get(localStorageItem)) {
|
||||
const dropdown_toggle = document.getElementById(dropdownID) as HTMLElement;
|
||||
if (dropdown_toggle) {
|
||||
dropdown_toggle.innerText = getLocalStorageValue(localStorageItem, dropdownID)!;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function applyDropdownEventListeners(dropdown: HTMLElement, optionalCallback?: () => void) {
|
||||
const dropdownSibling = document.getElementById(dropdown.id + "-menu")!;
|
||||
const localStorageItem = dropdown.dataset.localStorageKey as Alu.ValidStoreKeys;
|
||||
Array.from(dropdownSibling.children).forEach((child) => {
|
||||
const childEl = child as HTMLElement;
|
||||
childEl.onclick = () => {
|
||||
const localStorageItemContent: Alu.Key = {
|
||||
name: childEl.innerText,
|
||||
value: childEl.dataset.setting!,
|
||||
};
|
||||
Alu.store.set(localStorageItem, localStorageItemContent);
|
||||
applySavedLocalStorage(localStorageItem, dropdown.id);
|
||||
closeDropdown(dropdownSibling.id);
|
||||
if (typeof optionalCallback === "function") {
|
||||
optionalCallback();
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function applyInputListeners(input: HTMLInputElement, localStorageItem: Alu.ValidStoreKeys) {
|
||||
input.addEventListener("input", () => {
|
||||
Alu.store.set(localStorageItem, { value: input.value });
|
||||
});
|
||||
}
|
||||
|
||||
function addThemeToDropdown(extension: ExtensionMetadata) {
|
||||
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) => {
|
||||
const itemEl = item as HTMLElement;
|
||||
return itemEl.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);
|
||||
}
|
||||
}
|
||||
|
||||
loadContent("setting-tab-proxy");
|
||||
|
||||
function setupProxySettings() {
|
||||
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") as HTMLInputElement;
|
||||
const bareURLInput = document.getElementById("bare-url-input") as HTMLInputElement;
|
||||
|
||||
bareURLInput.value = Alu.store.get("bareUrl").value.toString();
|
||||
// Proxy settings
|
||||
[selectedProxyDropdown, openWithDropdown, currentTransportDropdown, wispURLDropdown].forEach((dropdown) => {
|
||||
applyDropdownEventListeners(dropdown!);
|
||||
});
|
||||
applyDropdownEventListeners(searchEngineDropdown!, checkSearxng);
|
||||
checkSearxng();
|
||||
|
||||
applyInputListeners(searxngUrlInput, "searxng");
|
||||
applyInputListeners(bareURLInput, "bareUrl");
|
||||
}
|
||||
|
||||
function setupCustomizationSettings() {
|
||||
const store = window.idb.transaction("InstalledExtensions", "readonly").objectStore("InstalledExtensions");
|
||||
store.getAll().onsuccess = (event) => {
|
||||
const result = (event.target as IDBRequest).result;
|
||||
if (result) {
|
||||
result.forEach((extension: ExtensionMetadata) => {
|
||||
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", () => {
|
||||
const cloakEl = cloak as HTMLElement;
|
||||
let cloakName = cloakEl.dataset.cloakName;
|
||||
let cloakIcon = cloakEl.dataset.cloakIcon;
|
||||
|
||||
const cloakItem = {
|
||||
name: cloakName,
|
||||
value: {
|
||||
name: cloakName,
|
||||
icon: cloakIcon,
|
||||
isCustom: false,
|
||||
},
|
||||
// eeyikes, make this better later.
|
||||
} as unknown as Alu.Key;
|
||||
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']") as HTMLLinkElement;
|
||||
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") as HTMLInputElement;
|
||||
const customFaviconInput = document.getElementById("cloak-custom-favicon-input") as HTMLInputElement;
|
||||
const cloak = Alu.store.get("cloak") as Alu.Key;
|
||||
if (cloak && typeof cloak.value == "object") {
|
||||
if (cloak.value.isCustom) {
|
||||
customNameInput.value = cloak.value.name;
|
||||
customFaviconInput.value = cloak.value.icon;
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("cloak-custom-button")!.addEventListener("click", () => {
|
||||
const cloakCustomName = document.getElementById("cloak-custom-name-input") as HTMLInputElement;
|
||||
const cloakCustomFavicon = document.getElementById("cloak-custom-favicon-input") as HTMLInputElement;
|
||||
let cloakName = cloakCustomName.value;
|
||||
let cloakIcon = cloakCustomFavicon.value;
|
||||
const cloakItem = {
|
||||
name: cloakName,
|
||||
icon: cloakIcon,
|
||||
isCustom: true,
|
||||
};
|
||||
// @ts-expect-error - Need to make cloak typing more standardized.
|
||||
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']") as HTMLLinkElement;
|
||||
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.toString());
|
||||
}
|
||||
|
||||
function setupSettings(event: CustomEvent) {
|
||||
addDropdownListener();
|
||||
if (event.detail == "setting-tab-proxy") {
|
||||
setupProxySettings();
|
||||
} 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");
|
||||
const searxInput = document.getElementsByClassName("setting__searxng-url")[0] as HTMLElement;
|
||||
if (searchEngine.value == "searx") {
|
||||
searxInput.style.opacity = "1";
|
||||
} else {
|
||||
searxInput.style.opacity = "0";
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("setting-tabLoad", (event) => {
|
||||
// I hate doing this :/
|
||||
setupSettings(event as CustomEvent);
|
||||
});
|
||||
|
||||
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", () => {
|
||||
settingsLoad();
|
||||
loadContent("setting-tab-proxy");
|
||||
});
|
||||
settingsLoad();
|
||||
|
|
@ -60,7 +60,7 @@
|
|||
"settings.cloaking.updateCloak": "Update Cloak",
|
||||
|
||||
"settings.credits": "Credits",
|
||||
"settings.credits.mochaandmacchiatothemes": "Mocha & Macchiato Themes",
|
||||
"settings.credits.catppuccin": "Catppuccin",
|
||||
"settings.credits.esTranslations": "Spanish Translations",
|
||||
"settings.credits.frTranslations": "French Translations",
|
||||
"settings.credits.jpTranslations": "Japanese Translations",
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@
|
|||
"settings.cloaking.updateCloak": "Capa de actualización",
|
||||
|
||||
"settings.credits": "Créditos",
|
||||
"settings.credits.mochaandmacchiatothemes": "Temas de Mocha y Macchiato",
|
||||
"settings.credits.catppuccin": "Temas de Mocha y Macchiato",
|
||||
"settings.credits.esTranslations": "Traducciones al español",
|
||||
"settings.credits.frTranslations": "Traducciones al francés",
|
||||
"settings.credits.jpTranslations": "Traducciones al japonés",
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@
|
|||
"settings.cloaking.subtext": "Changez l'apparence de votre fenêtre",
|
||||
"settings.cloaking.updateCloak": "Mettre à jour le déguise",
|
||||
"settings.credits": "Crédits",
|
||||
"settings.credits.mochaandmacchiatothemes": "Thème Moka & Macchiato",
|
||||
"settings.credits.esTranslations": "Traductions Espagnoles",
|
||||
"settings.credits.frTranslations": "Traductions Françaises",
|
||||
"settings.credits.jpTranslations": "Traductions Japonais",
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@
|
|||
"settings.cloaking.updateCloak": "クロークを更新",
|
||||
|
||||
"settings.credits": "クレジット",
|
||||
"settings.credits.mochaandmacchiatothemes": "モカとマキアートテーマ",
|
||||
"settings.credits.esTranslations": "スペイン語翻訳",
|
||||
"settings.credits.frTranslations": "フランス語翻訳",
|
||||
"settings.credits.jpTranslations": "日本語翻訳",
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@
|
|||
"settings.cloaking.updateCloak": "Alterar camuflagem",
|
||||
|
||||
"settings.credits": "Créditos",
|
||||
"settings.credits.mochaandmacchiatothemes": "Temas Mocha & Macchiato",
|
||||
"settings.credits.esTranslations": "Traduções espanholas",
|
||||
"settings.credits.frTranslations": "Traduções francesas",
|
||||
"settings.credits.jpTranslations": "Traduções japonesas",
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@
|
|||
"settings.cloaking.updateCloak": "Обновить плащ",
|
||||
|
||||
"settings.credits": "Кредиты",
|
||||
"settings.credits.mochaandmacchiatothemes": "Mocha и Macchiato Темы",
|
||||
"settings.credits.esTranslations": "Испанские переводы",
|
||||
"settings.credits.frTranslations": "Французские переводы",
|
||||
"settings.credits.jpTranslations": "Японские переводы",
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@
|
|||
"settings.cloaking.updateCloak": "更新斗篷",
|
||||
|
||||
"settings.credits": "致谢",
|
||||
"settings.credits.mochaandmacchiatothemes": "Mocha 和 Macchiato 主题",
|
||||
"settings.credits.esTranslations": "西班牙语翻译",
|
||||
"settings.credits.frTranslations": "法语翻译",
|
||||
"settings.credits.jpTranslations": "日语翻译",
|
||||
|
|
|
|||
|
|
@ -55,326 +55,7 @@ export function getStaticPaths() {
|
|||
<div id="current-content"></div>
|
||||
</div>
|
||||
</main>
|
||||
<script>
|
||||
window.loadedContentStorage = {};
|
||||
window.currentlySelectedTab;
|
||||
document.addEventListener("astro:before-swap", () => {
|
||||
window.currentlySelectedTab = "";
|
||||
});
|
||||
function settingsLoad() {
|
||||
Array.from(document.getElementsByClassName("setting-tab")).forEach((tab) => {
|
||||
const contentToLoad = document.getElementById("content-" + tab.id);
|
||||
if (contentToLoad) {
|
||||
window.loadedContentStorage[tab.id] = contentToLoad.innerHTML;
|
||||
contentToLoad.remove();
|
||||
}
|
||||
|
||||
tab.addEventListener("click", (event: Event) => {
|
||||
const target = event.target as HTMLElement;
|
||||
loadContent(target.id);
|
||||
});
|
||||
});
|
||||
}
|
||||
function loadContent(tabID: string) {
|
||||
if (window.currentlySelectedTab == tabID) return;
|
||||
else window.currentlySelectedTab = tabID;
|
||||
const 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-tabLoad", { detail: tabID }));
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
|
||||
function addDropdownListener() {
|
||||
const dropdown_toggles = document.getElementsByClassName("dropdown-toggle") as HTMLCollectionOf<HTMLElement>;
|
||||
Array.from(dropdown_toggles).forEach((toggle) => {
|
||||
toggle.onclick = function () {
|
||||
closeOtherDropdowns(toggle.id);
|
||||
toggleDropdown(toggle);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function toggleDropdown(toggle: HTMLElement) {
|
||||
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 closeOtherDropdowns(dropdownIDToExclude: string) {
|
||||
const dropdowns = document.getElementsByClassName("dropdown-menu") as HTMLCollectionOf<HTMLElement>;
|
||||
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: string) {
|
||||
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: Alu.ValidStoreKeys, dropdownID: string) {
|
||||
// I was kinda dumb for not doing this earlier.
|
||||
const dropdown = document.getElementById(dropdownID);
|
||||
const dropdownMenu = document.getElementById(dropdownID + "-menu") as HTMLElement;
|
||||
|
||||
if (dropdown && dropdownMenu) {
|
||||
// Now we find the child that matches localStorageItem.value.
|
||||
const dropdownItem = Array.from(dropdownMenu.children).find((item) => {
|
||||
const itemEl = item as HTMLElement;
|
||||
return Alu.store.get(localStorageItem).value == itemEl.dataset.setting;
|
||||
}) as HTMLElement;
|
||||
// Now set the inner text to the name in the dropdownItem.
|
||||
return dropdownItem.innerText;
|
||||
}
|
||||
}
|
||||
|
||||
function applySavedLocalStorage(localStorageItem: Alu.ValidStoreKeys, dropdownID: string) {
|
||||
if (Alu.store.get(localStorageItem)) {
|
||||
const dropdown_toggle = document.getElementById(dropdownID) as HTMLElement;
|
||||
if (dropdown_toggle) {
|
||||
dropdown_toggle.innerText = getLocalStorageValue(localStorageItem, dropdownID)!;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function applyDropdownEventListeners(dropdown: HTMLElement, optionalCallback?: Function) {
|
||||
const dropdownSibling = document.getElementById(dropdown.id + "-menu")!;
|
||||
const localStorageItem = dropdown.dataset.localStorageKey as Alu.ValidStoreKeys;
|
||||
Array.from(dropdownSibling.children).forEach((child) => {
|
||||
const childEl = child as HTMLElement;
|
||||
childEl.onclick = () => {
|
||||
const localStorageItemContent: Alu.Key = {
|
||||
name: childEl.innerText,
|
||||
value: childEl.dataset.setting!,
|
||||
};
|
||||
Alu.store.set(localStorageItem, localStorageItemContent);
|
||||
applySavedLocalStorage(localStorageItem, dropdown.id);
|
||||
closeDropdown(dropdownSibling.id);
|
||||
if (typeof optionalCallback === "function") {
|
||||
optionalCallback();
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function applyInputListeners(input: HTMLInputElement, localStorageItem: Alu.ValidStoreKeys) {
|
||||
input.addEventListener("input", () => {
|
||||
Alu.store.set(localStorageItem, { value: input.value });
|
||||
});
|
||||
}
|
||||
|
||||
function addThemeToDropdown(extension: ExtensionMetadata) {
|
||||
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) => {
|
||||
const itemEl = item as HTMLElement;
|
||||
return itemEl.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", addDropdownListener);
|
||||
|
||||
loadContent("setting-tab-proxy");
|
||||
|
||||
function setupCustomizationSettings() {
|
||||
const store = window.idb.transaction("InstalledExtensions", "readonly").objectStore("InstalledExtensions");
|
||||
store.getAll().onsuccess = (event) => {
|
||||
const result = (event.target as IDBRequest).result;
|
||||
if (result) {
|
||||
result.forEach((extension: ExtensionMetadata) => {
|
||||
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", () => {
|
||||
const cloakEl = cloak as HTMLElement;
|
||||
let cloakName = cloakEl.dataset.cloakName;
|
||||
let cloakIcon = cloakEl.dataset.cloakIcon;
|
||||
|
||||
const cloakItem = {
|
||||
name: cloakName,
|
||||
value: {
|
||||
name: cloakName,
|
||||
icon: cloakIcon,
|
||||
isCustom: false,
|
||||
},
|
||||
// eeyikes, make this better later.
|
||||
} as unknown as Alu.Key;
|
||||
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']") as HTMLLinkElement;
|
||||
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") as HTMLInputElement;
|
||||
const customFaviconInput = document.getElementById("cloak-custom-favicon-input") as HTMLInputElement;
|
||||
const cloak = Alu.store.get("cloak") as Alu.Key;
|
||||
if (cloak && typeof cloak.value == "object") {
|
||||
if (cloak.value.isCustom) {
|
||||
customNameInput.value = cloak.value.name;
|
||||
customFaviconInput.value = cloak.value.icon;
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("cloak-custom-button")!.addEventListener("click", () => {
|
||||
const cloakCustomName = document.getElementById("cloak-custom-name-input") as HTMLInputElement;
|
||||
const cloakCustomFavicon = document.getElementById("cloak-custom-favicon-input") as HTMLInputElement;
|
||||
let cloakName = cloakCustomName.value;
|
||||
let cloakIcon = cloakCustomFavicon.value;
|
||||
const cloakItem = {
|
||||
name: cloakName,
|
||||
icon: cloakIcon,
|
||||
isCustom: true,
|
||||
};
|
||||
// @ts-expect-error - Need to make cloak typing more standardized.
|
||||
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']") as HTMLLinkElement;
|
||||
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.toString());
|
||||
}
|
||||
|
||||
function setupSettings(event: any) {
|
||||
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") as HTMLInputElement;
|
||||
const bareURLInput = document.getElementById("bare-url-input") as HTMLInputElement;
|
||||
|
||||
bareURLInput.value = Alu.store.get("bareUrl").value.toString();
|
||||
// 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");
|
||||
const searxInput = document.getElementsByClassName("setting__searxng-url")[0] as HTMLElement;
|
||||
if (searchEngine.value == "searx") {
|
||||
searxInput.style.opacity = "1";
|
||||
} else {
|
||||
searxInput.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", () => {
|
||||
settingsLoad();
|
||||
loadContent("setting-tab-proxy");
|
||||
});
|
||||
settingsLoad();
|
||||
</script>
|
||||
<script src="@components/ts/settings.ts"></script>
|
||||
<style is:global>
|
||||
.content-hidden {
|
||||
display: none;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue