From 7c6b962ece7730eabc3056f79c9463528860cd34 Mon Sep 17 00:00:00 2001 From: LEGALISE_PIRACY Date: Tue, 30 Jan 2024 01:28:06 +0000 Subject: [PATCH] Upload files to "v4/js" --- v4/js/games.js | 218 ++++++++++++++++++++++++++++++++++++++++ v4/js/home.js | 84 ++++++++++++++++ v4/js/index.js | 245 +++++++++++++++++++++++++++++++++++++++++++++ v4/js/main.js | 61 ++++++++++++ v4/js/settings.js | 248 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 856 insertions(+) create mode 100644 v4/js/games.js create mode 100644 v4/js/home.js create mode 100644 v4/js/index.js create mode 100644 v4/js/main.js create mode 100644 v4/js/settings.js diff --git a/v4/js/games.js b/v4/js/games.js new file mode 100644 index 00000000..eb48b75f --- /dev/null +++ b/v4/js/games.js @@ -0,0 +1,218 @@ +/* +Hello epic hacker (maybe skid) you are looking at one of the many scripts that powers the site, +this script has extra comments and info to help you understand what is going on. + +This is a JavaScript code that creates a game catalog page with a search feature, +a game detail page, and the ability to save and load user data. + +It uses fetch to load game data from a JSON file, creates game elements for each game, +and adds click event listeners to show the game in a game container. + +The code also includes functions to handle saving and loading user data as well as a function to handle a specific key sequence. +*/ +// Select the elements +const gamesContainer = document.querySelector(".games"); +const searchBar = document.querySelector(".searchbar"); +const gameContainer = document.querySelector(".gamecontainer"); +const gameFrame = gameContainer.querySelector(".frame"); +const gameNav = gameContainer.querySelector(".nav"); + +// Listen for input event on the search bar +searchBar.addEventListener("input", (e) => { + const query = searchBar.value.trim().toLowerCase(); + + // Loop through all the games in the container and show/hide them depending on whether they match the search query + for (let game of gamesContainer.children) { + if (game instanceof Element) { + if (query) { + const gameName = game + .querySelector("span") + .innerText.trim() + .toLowerCase(); + if (gameName.includes(query)) { + game.removeAttribute("hidden"); + } else { + game.setAttribute("hidden", ""); + } + } else { + game.removeAttribute("hidden"); + } + } + } + + // If there are no games shown, display the "No games" message, otherwise hide it + if (document.querySelectorAll(".game:not([hidden])").length == 0) { + document.querySelector(".nogames").style.display = "initial"; + } else { + document.querySelector(".nogames").style.display = "none"; + } +}); + +// Fetch the games data from a JSON file +fetch("./assets/json/games.json") + .then((res) => res.json()) + .then((games) => { + // Loop through each game and create a new game element for it + games.forEach((game) => { + const gameEl = document.createElement("div"); + gameEl.className = "game"; + gameEl.innerHTML = `${game.name}`; + gamesContainer.appendChild(gameEl); + + // Add click event listener to the game element to show the game in the game container + gameEl.onclick = (e) => { + gamesContainer.classList.add("hidden"); + searchBar.classList.add("hidden"); + gameContainer.classList.remove("hidden"); + document.querySelector(".saveItems").classList.add("hidden"); + document.querySelector(".navbar").classList.add("noshadow"); + gameFrame.querySelector( + "iframe" + ).src = `./assets/game.html?game=${game.root}`; + gameNav.querySelector("span").textContent = game.name; + }; + + // Add click event listener to the back button in the game container to go back to the games list + gameNav.querySelector("#back").addEventListener("click", (e) => { + gamesContainer.classList.remove("hidden"); + searchBar.classList.remove("hidden"); + gameContainer.classList.add("hidden"); + document.querySelector(".saveItems").classList.remove("hidden"); + document.querySelector(".navbar").classList.remove("noshadow"); + gameFrame.src = ""; + }); + + // Add click event listener to the fullscreen button in the game container to enter fullscreen mode + gameNav.querySelector("#fullscreen").addEventListener("click", (e) => { + if (!document.fullscreenElement) { + gameFrame.requestFullscreen(); + } + }); + }); + }) + .catch((e) => { + alert("Could not load games"); + alert(e); + }); + +// Hide the spinner element after the page is loaded +document.querySelector(".spinner").style.display = "none"; + +// Function to get the main save data +function getMainSave() { + var mainSave = {}; + + // List of items in localStorage that should not be saved + var localStorageDontSave = ["theme", "tab", "nebelung"]; + + // Convert localStorage to an array of key-value pairs and remove the items that should not be saved + let localStorageSave = Object.entries(localStorage); + + for (let entry in localStorageSave) { + if (localStorageDontSave.includes(localStorageSave[entry][0])) { + localStorageSave.splice(entry, 1); + } + } + + // Convert the localStorage array to a base64-encoded JSON string + localStorageSave = btoa(JSON.stringify(localStorageSave)); + + // Add the localStorage data to the mainSave object + mainSave.localStorage = localStorageSave; + + // Get the cookies data and add it to the mainSave object + cookiesSave = document.cookie; + cookiesSave = btoa(cookiesSave); + mainSave.cookies = cookiesSave; + + // Convert the mainSave object to a base64-encoded JSON string + mainSave = btoa(JSON.stringify(mainSave)); + + // Encrypt the mainSave data using AES encryption with the key 'save' + mainSave = CryptoJS.AES.encrypt(mainSave, "save").toString(); + + // Return the encrypted mainSave data + return mainSave; +} + +// Function to download the main save data as a file +function downloadMainSave() { + var data = new Blob([getMainSave()]); + var dataURL = URL.createObjectURL(data); + + var fakeElement = document.createElement("a"); + fakeElement.href = dataURL; + fakeElement.download = "games.save"; + fakeElement.click(); + URL.revokeObjectURL(dataURL); +} + +// Function to get the main save data from an uploaded file +function getMainSaveFromUpload(data) { + // Decrypt the uploaded data using AES decryption with the key 'save' + data = CryptoJS.AES.decrypt(data, "save").toString(CryptoJS.enc.Utf8); + + // Parse the decrypted data as JSON + var mainSave = JSON.parse(atob(data)); + var mainLocalStorageSave = JSON.parse(atob(mainSave.localStorage)); + var cookiesSave = atob(mainSave.cookies); + + // Set the items in localStorage using the uploaded data + for (let item of mainLocalStorageSave) { + localStorage.setItem(item[0], item[1]); + } + + // Set the cookies using the uploaded data + document.cookie = cookiesSave; +} + +// Function to handle the file upload +function uploadMainSave() { + var hiddenUpload = document.querySelector(".hiddenUpload"); + hiddenUpload.click(); + + // Listen for the change event on the file input element + hiddenUpload.addEventListener("change", function (e) { + var files = e.target.files; + var file = files[0]; + if (!file) { + return; + } + + // Read the contents of the uploaded file as text and call getMainSaveFromUpload with the result + var reader = new FileReader(); + + reader.onload = function (e) { + getMainSaveFromUpload(e.target.result); + + // Show a success message to the user + var uploadResult = document.querySelector(".uploadResult"); + uploadResult.innerText = "Uploaded save!"; + uploadResult.style.display = "initial"; + setTimeout(function () { + uploadResult.style.display = "none"; + }, 3000); + }; + + reader.readAsText(file); + }); +} + +// Handle the hii pattern when keys are pressed +var hiiPattern = ["h", "i", "i"]; +var hiiCurrent = 0; + +document.addEventListener("keydown", function (e) { + if (e.key !== hiiPattern[hiiCurrent]) { + return (hiiCurrent = 0); + } + + hiiCurrent++; + + if (hiiPattern.length == hiiCurrent) { + hiiCurrent = 0; + document.querySelector(".hii").removeAttribute("hidden"); + } +}); diff --git a/v4/js/home.js b/v4/js/home.js new file mode 100644 index 00000000..0c6d4c63 --- /dev/null +++ b/v4/js/home.js @@ -0,0 +1,84 @@ +/* +Hello epic hacker (maybe skid) you are looking at one of the many scripts that powers the site, +this script has extra comments and info to help you understand what is going on. + +This is a JavaScript code that generates random splash messages and sets them in the DOM. + +The code declares two variables for caching splash messages, "splashCacheAll" and "splashCache". + +The "randomSay" function fetches a set of splash messages and selects a random one from the set, +caching the remaining messages in the "splashCache" variable. + +If the selected message contains special placeholders like "%REAL_IP%", "%GAMES_NUMBER%", or "%SPLASH_NUMBER%", +the placeholders are replaced with corresponding values, such as the user's IP address, the number of available games, +or the total number of splash messages. The "setRandomSay" function sets the selected splash message in the DOM. + +If there is an element with class "message", the "setRandomSay" function is called to set a random splash message in the DOM. +*/ + +// Declare variables for caching splash messages +var splashCacheAll; +var splashCache; + +// Async function that returns a random splash message +async function randomSay() { + // If splashCache is defined and not empty + if (splashCache) { + // If splashCache is empty, set it equal to the full set of splash messages + if (!splashCache.length) { + splashCache = splashCacheAll; + } + // Set says variable to the current splashCache + var says = splashCache; + } else { + // If splashCache is undefined or empty, fetch the full set of splash messages + var say = await fetch("./assets/json/say.json"); + var says = await say.json(); + // Store the full set of splash messages in both splashCacheAll and splashCache + splashCacheAll = says; + splashCache = says; + } + + // Get a random splash message from the current says set + var getRandomSay = says[Math.floor(Math.random() * says.length)]; + + // Remove the randomly selected splash message from the cache + splashCache = splashCache.filter((splash) => splash !== getRandomSay); + + // Return the randomly selected splash message + return getRandomSay; +} + +// Async function that sets a random splash message in the DOM +async function setRandomSay() { + // Get a random splash message using the randomSay() function + var randomSplash = await randomSay(); + + // If the random message is "%REAL_IP%", replace it with the user's IP address + if (randomSplash == "%REAL_IP%") { + var ips = await getIPs(); + if (ips[0]) { + randomSplash = "Your real IP is " + ips[0]; + } else { + randomSplash = "Cannot get your real IP :("; + } + } + // If the random message is "%GAMES_NUMBER%", replace it with the number of games available + else if (randomSplash == "%GAMES_NUMBER%") { + var gamesFetch = await fetch(location.origin + "/assets/json/games.json"); + var games = await gamesFetch.json(); + randomSplash = "There are " + games.length + " games currently"; + } + // If the random message is "%SPLASH_NUMBER%", replace it with the total number of splash messages + else if (randomSplash == "%SPLASH_NUMBER%") { + randomSplash = "There are " + splashCacheAll.length + " of these messages!"; + } + + // Set the random splash message in the DOM + document.querySelector(".message").innerText = randomSplash; +} + +// If there is an element with class "message", set a random splash message in the DOM +if (document.querySelector(".message")) { + setRandomSay(); +} diff --git a/v4/js/index.js b/v4/js/index.js new file mode 100644 index 00000000..dd42c962 --- /dev/null +++ b/v4/js/index.js @@ -0,0 +1,245 @@ +/* +Hello epic hacker (maybe skid) you are looking at one of the many scripts that powers the site, +this script has extra comments and info to help you understand what is going on. + +This code starts off with a script to check if the browser has a cookie, if not, it will display a message kindly asking for the user to turn off their adblocker. Then it sets the cookie so the message is not seen for another year. + +The code sets up several variables and functions that are used to fetch data from the server, +manipulate the document's content, and create custom HTML elements. + +The isBlocked function checks if a URL is blocked by fetching the content of its README.md +file and returning true if it does not start with "# 3kh0 Assets", +or if there is an error while fetching the file. + +The getCDN function iterates through a list of CDN URLs, calls isBlocked on each of them, +and returns the first URL that is not blocked, +or the first URL in the list if they are all blocked. + +The rest of the code sets up various event listeners and HTML elements, loads the main.js file, +and sets the website's theme and theme colors based on values in local storage. + +The code is mostly concerned with setting up the website's initial state and is executed when the website loads. +*/ + +// This function checks if a cookie with the given key exists. +function checkCookie(key) { + var value = "; " + document.cookie; // get the cookie value + var parts = value.split("; " + key + "="); // split the value by the key + if (parts.length == 2) { + return true; // the key exists + } else { + return false; // the key does not exist + } +} + +// Checks if a CDN is blocked by testing the README.md file +async function isBlocked(url) { + try { + var README = await fetch(url + "/README.md"); + var content = await README.text(); + if (content.startsWith("# 3kh0 Assets")) { + // The CDN is not blocked + return false; + } else { + // The CDN is not returning a valid response or is blocked + return true; + } + } catch { + return true; + } +} + +async function getCDN(cdns) { + for (let cdn of cdns) { + var blocked = await isBlocked(cdn); + if (!blocked) { + return cdn; + } + } + return cdns[0]; +} + +// Define some varibles for later +const path = location.pathname; +const origin = localStorage.getItem("instance"); +const cdn = localStorage.getItem("cdn"); +const bare = localStorage.getItem +const queryString = window.location.search; +window.history.pushState({}, "", path); +const urlParams = new URLSearchParams(queryString); +const onLoadData = urlParams.get("onload"); + +function clearCdnCache() { + fetch("./assets/json/cdns.json") + .then((res) => res.json()) + .then(async (cdns) => { + localStorage.setItem("cdn", await getCDN(cdns)); + location.reload(); + }); +} + +const base = document.createElement("base"); +base.href = + location.origin + path.replace(path.split("\\").pop().split("/").pop(), ""); +document.head.appendChild(base); + +// If we do not have the origin var, we make it +if (!origin) { + localStorage.setItem("instance", base.href); + location.reload(); +} + +// If we do not have the cdn var, we make it +if (!cdn) { + fetch("./assets/json/cdns.json") + .then((res) => res.json()) + .then(async (cdns) => { + localStorage.setItem("cdn", await getCDN(cdns)); + location.reload(); + }); +} + +if (!cdn) { + fetch("./assets/json/cdns.json") + .then((res) => res.json()) + .then(async (cdns) => { + localStorage.setItem("cdn", await getCDN(cdns)); + location.reload(); + }); +} + +const instance = encodeURIComponent(origin.replace(location.origin, "")); + +// If we have onLoadData, we run it now + +// If we have any errors, we will log it +window.addEventListener("error", (e) => { + console.error(e); +}); + +// Add the main script in the tags + +// Collect Tab Cloak data from local storage +var tab = localStorage.getItem("tab"); +if (tab) { + try { + // Parse the data, it is in JSON + var tabData = JSON.parse(tab); + } catch { + var tabData = {}; + } +} else { + var tabData = {}; +} + +// Set the Tab title if the Tab cloak data is there +if (tabData.title) { + document.title = tabData.title; +} + +// Set the Tab icon if the Tab cloak data is there +if (tabData.icon) { + document.querySelector('link[rel="icon"]').href = tabData.icon; +} + +// Set theme colors if the user has set it +function getContrastHex(hexcolor) { + hexcolor = hexcolor.replace("#", ""); + var r = parseInt(hexcolor.substr(0, 2), 16); + var g = parseInt(hexcolor.substr(2, 2), 16); + var b = parseInt(hexcolor.substr(4, 2), 16); + var yiq = (r * 299 + g * 587 + b * 114) / 1000; + return yiq >= 128 ? "#1c1c1c" : "white"; +} + +// Set theme colors if the user has set it +function getColorHex(hexcolor) { + hexcolor = hexcolor.replace("#", ""); + var r = parseInt(hexcolor.substr(0, 2), 16); + var g = parseInt(hexcolor.substr(2, 2), 16); + var b = parseInt(hexcolor.substr(4, 2), 16); + var yiq = (r * 299 + g * 587 + b * 114) / 1000; + return yiq >= 128 ? "white" : "black"; +} + +// Set theme colors if the user has set it +var theme = localStorage.getItem("theme") || "default"; +let themes; + +// Fetching themes +fetch(origin + "assets/json/themes.json") + .then((res) => res.json()) + .then((data_themes) => { + themes = data_themes; + + if (theme !== "custom") { + document.body.setAttribute("theme", theme); + + if (location.pathname.includes("/settings")) { + themes.forEach((palette) => { + if (palette.theme == theme) { + console.log(palette.theme); + document.querySelector("#theme_color").value = palette.color; + } + }); + } + } else { + // Get custom theme + const theme = localStorage.getItem("theme_color"); + + document.body.setAttribute("theme", "custom"); + document.body.style = `--theme: ${theme}; --background: ${getContrastHex( + theme + )}; --text: ${getColorHex(theme)}; --text-secondary: ${getColorHex( + theme + )};`; + + if (location.pathname.includes("/settings")) { + // Make the custom theme color selector + document.querySelector("#theme_color").value = theme; + } + } + }) + .catch((e) => { + // Houston, we have a problem. + console.error(e); + throw new Error("Failed to load themes"); + }); + +// Add the changelogAdded element for the changelog + +// Parrot theme random colors +function setParrotColors() { + var parrotColor = "rgb(195, 158, 31)"; + var parrotColors = ["#ff4c4b", "#c39e1f", "#b42e63"]; + + document.querySelectorAll("*").forEach((item) => { + if (getComputedStyle(item).color == parrotColor) { + item.style.color = + parrotColors[Math.floor(Math.random() * parrotColors.length)]; + } + }); +} + +if (localStorage.getItem("theme") == "parrot") { + setParrotColors(); +} + +// Handle secret themes +function foundSecretTheme(name) { + document.body.setAttribute("theme", name); + localStorage.setItem("theme", name); + localStorage.setItem(name, "true"); + if (document.querySelector("." + name)) { + document.querySelector("." + name).removeAttribute("hidden"); + } +} + +// Handle the secret theme button +function secretThemeButton(name) { + if (localStorage.getItem(name) == "true") { + if (document.querySelector("." + name)) { + document.querySelector("." + name).removeAttribute("hidden"); + } + } +} \ No newline at end of file diff --git a/v4/js/main.js b/v4/js/main.js new file mode 100644 index 00000000..36ddfe55 --- /dev/null +++ b/v4/js/main.js @@ -0,0 +1,61 @@ +/* +Hello there! +If you want to add these games to your site, please reach out at my email: echo-the-coder@tuta.io, +or discord: 3kh0_#6969, Thanks and have a great day! + +Wondering how this works? +This JavaScript code begins with a console warning message that asks users to reach out via email if they +want to add the games to their website. + +The second part of the code defines a function called "script" that logs an informational message to the console when it is called. +The rest of the code creates four separate script tags and adds them to the head of the HTML document. + +Each script tag has different attributes and sources, and is appended with the script function. +The first script tag is for Google Tag Manager, the second is for the Arc.io widget, the third is for ad handling using Google Funding Choices, +and the fourth is for Google AdSense. + +Each script is added to the page asynchronously for performance reasons. +*/ +console.warn( + "%cNote!", + "color: purple; font-weight: 600; background: yellow; padding: 0 5px; border-radius: 5px", + "If you want to add these games to your site, please reach out at my email: echo-the-coder@tuta.io\nPlease do not just add them without asking me first! Thank you!" +); + +// function script(text) { +// console.log("%cScript Injection", "color: cyan; font-weight: 600; background: black; padding: 0 5px; border-radius: 5px", text); +// } + +// // ==================================== +// // SCRIPT INJECTION +// // ==================================== +// const gogascript27 = document.createElement("script"); +// gogascript27.setAttribute("async", ""); +// gogascript27.setAttribute("src", "https://www.googletagmanager.com/gtag/js?id=G-98DP5VKS42"); +// const inlinegogascript843 = document.createElement("script"); +// inlinegogascript843.innerHTML = `window.dataLayer = window.dataLayer || []; +// function gtag(){dataLayer.push(arguments);} +// gtag('js', new Date()); +// gtag('config', 'G-98DP5VKS42');`; +// document.head.append(gogascript27, inlinegogascript843); +// script("Injected script 1/4 (Google Tag Manager)"); + +// const arcbroker23 = document.createElement("script"); +// arcbroker23.setAttribute("async", ""); +// arcbroker23.setAttribute("src", "https://arc.io/widget.min.js#eRPHFgiC"); +// document.head.append(arcbroker23); +// script("Injected script 2/4 (Arc widget stuff)"); + +// const adblockhandle44 = document.createElement("script"); +// adblockhandle44.setAttribute("src", "https://fundingchoicesmessages.google.com/i/pub-5756835229788588?ers=1"); +// adblockhandle44.setAttribute("nonce", "yibq-w_TR5NOCRWsU-VL0Q"); +// adblockhandle44.setAttribute("async", ""); +// document.head.append(adblockhandle44); +// script("Injected script 3/4 (Ad stuff)"); + +// const adscipterz92 = document.createElement("script"); +// adscipterz92.setAttribute("async", ""); +// adscipterz92.setAttribute("src", "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5756835229788588"); +// adscipterz92.setAttribute("crossorigin", "anonymous"); +// document.head.append(adscipterz92); +// script("Injected script 4/4 (Ad stuff)"); diff --git a/v4/js/settings.js b/v4/js/settings.js new file mode 100644 index 00000000..5ee06b31 --- /dev/null +++ b/v4/js/settings.js @@ -0,0 +1,248 @@ +/* +Hello epic hacker (maybe skid) you are looking at one of the many scripts that powers the site, +this script has extra comments and info to help you understand what is going on. + +This JavaScript code defines functions that manage the state of a web page's tab, +such as its title and icon, and its theme. + +It retrieves a JSON object from local storage, which contains the current state of the tab, +and updates the web page's elements with the stored values. + +The code provides functions to modify the tab state and settings, such as setTitle, setFavicon, +resetTab, setTheme, and setThemeColor. + +These functions update the web page's elements and store the updated state in local storage. +*/ + +// Check if there is a saved tab data in localStorage +var tab = localStorage.getItem("tab"); + +if (tab) { + // If there is saved data, try to parse it + try { + var tabData = JSON.parse(tab); + } catch { + // If there is an error in parsing, create an empty object + var tabData = {}; + } +} else { + // If there is no saved data, create an empty object + var tabData = {}; +} + +// Set the title and icon fields to the values saved in tabData, if they exist +if (tabData.title) { + document.getElementById("title").value = tabData.title; +} +if (tabData.icon) { + document.getElementById("icon").value = tabData.icon; +} + +// Default tab settings +var settingsDefaultTab = { + title: "Settings | 3kh0", + icon: "./images/logo.png", +}; + +// Function to set the document title +function setTitle(title = "") { + if (title) { + document.title = title; + } else { + document.title = settingsDefaultTab.title; + } + + // Update the saved tab data with the new title + var tab = localStorage.getItem("tab"); + + if (tab) { + // If there is saved data, try to parse it + try { + var tabData = JSON.parse(tab); + } catch { + // If there is an error in parsing, create an empty object + var tabData = {}; + } + } else { + // If there is no saved data, create an empty object + var tabData = {}; + } + + if (title) { + // If there is a new title, update tabData + tabData.title = title; + } else { + // If the title is empty, delete the title field from tabData + delete tabData.title; + } + + // Save the updated tab data to localStorage + localStorage.setItem("tab", JSON.stringify(tabData)); +} + +// Function to set the favicon +function setFavicon(icon) { + if (icon) { + document.querySelector("link[rel='icon']").href = icon; + } else { + document.querySelector("link[rel='icon']").href = settingsDefaultTab.icon; + } + + // Update the saved tab data with the new icon + var tab = localStorage.getItem("tab"); + + if (tab) { + // If there is saved data, try to parse it + try { + var tabData = JSON.parse(tab); + } catch { + // If there is an error in parsing, create an empty object + var tabData = {}; + } + } else { + // If there is no saved data, create an empty object + var tabData = {}; + } + + if (icon) { + // If there is a new icon, update tabData + tabData.icon = icon; + } else { + // If the icon is empty, delete the icon field from tabData + delete tabData.icon; + } + + // Save the updated tab data to localStorage + localStorage.setItem("tab", JSON.stringify(tabData)); +} + +function setCloak() { + // applies only to premade cloaks + var cloak = document.getElementById("premadecloaks").value; // cloak seems kind of weird when you spell it out + switch (cloak) { + case "search": // Google Search + setTitle("Google"); + setFavicon("./images/cloaks/Google Search.ico"); + location.reload(); + break; + case "itchio": // itch.io + setTitle("Top free NSFW games for web"); + setFavicon("./images/cloaks/D23D344B-4CB0-4799-B525-F4E4F3A36728.ico"); + location.reload(); + break; + case "wikipedia": // wikipedia + setTitle("ويكيبيديا - جهاد"); + setFavicon("https://ar.wikipedia.org/favicon.ico"); + location.reload(); + break; + case "bsite": // billibilli + setTitle("Billibilli"); + setFavicon("https://www.bilibili.com/favicon.ico"); + location.reload(); + break; + case "drive": // Google Drive + setTitle("My Drive - Google Drive"); + setFavicon("./images/cloaks/Google Drive.ico"); + location.reload(); + break; + case "librex": // LibreX + setTitle("LibreX"); + setFavicon("./images/cloaks/9A58D8BC-6595-476A-AD95-B6D8880683C8.ico"); + location.reload(); + break; + case "youtube": // YouTube + setTitle("YouTube"); + setFavicon("./images/cloaks/YouTube.ico"); + location.reload(); + break; + case "gmail": // Gmail + setTitle("Gmail"); + setFavicon("./images/cloaks/Gmail.ico"); + location.reload(); + break; + case "calendar": // Google Calendar + setTitle("Google Calendar"); + setFavicon("./images/cloaks/Calendar.ico"); + location.reload(); + break; + case "meets": // Google Meet + setTitle("Google Meet"); + setFavicon("./images/cloaks/Meet.ico"); + location.reload(); + break; + case "classroom": // Google Classroom + setTitle("Classes"); + setFavicon("./images/cloaks/Classroom.png"); + location.reload(); + break; + case "canvas": // Canvas + setTitle("Canvas"); + setFavicon("./images/cloaks/Canvas.ico"); + location.reload(); + break; + case "zoom": // Zoom + setTitle("Zoom"); + setFavicon("./images/cloaks/Zoom.ico"); + location.reload(); + break; + case "nitter": // Nitter + setTitle("nitter"); + setFavicon("./images/cloaks/63DFB320-0EEC-4F06-AF02-C50DFD2B49AB.ico"); + location.reload(); + break; + case "teddit": // Teddit + setTitle("teddit"); + setFavicon("./images/cloaks/EB4D8FE9-10E9-44B8-A6CE-3F9A0040F94A.ico"); + location.reload(); + break; + case "cornhub": // Cornhub + setTitle("Cornhub"); + setFavicon("./images/cloaks/8FE4C273-914D-431D-907E-3FCF5BB0399F.ico"); + location.reload(); + break; + case "indivious": // Indivious + setTitle("Indivious"); + setFavicon("./images/cloaks/2255E848-AB69-43C1-B470-DBFDA40FAD10.ico"); + location.reload(); + break; + case "khan": // Khan Academy + setTitle("Dashboard | Khan Academy"); + setFavicon("./images/cloaks/Khan Academy.ico"); + location.reload(); + break; + } +} + +// Function to reset the tab settings to default +function resetTab() { + document.title = settingsDefaultTab.title; + document.querySelector("link[rel='icon']").href = settingsDefaultTab.icon; + document.getElementById("title").value = ""; + document.getElementById("icon").value = ""; + localStorage.setItem("tab", JSON.stringify({})); +} + +// Function to set the theme +function setTheme(theme) { + localStorage.setItem("theme", theme); + document.body.setAttribute("theme", theme); + document.body.style = ""; + localStorage.removeItem("theme_color"); + + // Find the theme color from the themes array and set the color + themes.forEach((palette) => { + if (palette.theme == theme) { + document.querySelector("#theme_color").value = palette.color; + } + }); +} + +// Function to set the custom theme color +function setThemeColor(theme) { + localStorage.setItem("theme", "custom"); + localStorage.setItem("theme_color", theme); + document.body.setAttribute("theme", "custom"); + document.body.style = `--theme: ${theme}; --background: ${getContrastHex( + theme + )}; --text: ${getColorHex(theme)}; --text-secondary: ${getColorHex(theme)};`; +}