added experimental theming system

This commit is contained in:
SethBurkart123
2023-10-29 16:16:31 +11:00
parent d723c128e4
commit f28cb23656
6 changed files with 118 additions and 137 deletions
+1
View File
@@ -34,6 +34,7 @@
"autoprefixer": "^10.4.15",
"color": "^4.2.3",
"install": "^0.13.0",
"localforage": "^1.10.0",
"motion": "^10.16.4",
"npm": "^10.1.0",
"postcss": "^8.4.29",
File diff suppressed because one or more lines are too long
-126
View File
@@ -1,126 +0,0 @@
/* global localforage */
/**
* 🎨 Theme Management Functions 🎨
*/
/**
* Fetches theme details (CSS, images, className) from a given URL.
* @param {string} url - The URL to fetch theme JSON from.
* @returns {Object} - Theme details including CSS, images, and class name.
*/
async function fetchThemeJSON(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch theme JSON: ${response.statusText}`);
}
const data = await response.json();
const cssResponse = await fetch(data.css);
if (!cssResponse.ok) {
throw new Error(`Failed to fetch CSS: ${cssResponse.statusText}`);
}
const cssText = await cssResponse.text();
return {
css: cssText,
images: data.images,
className: data.className,
};
}
/**
* Saves theme details to IndexedDB storage via localForage.
* @param {Object} theme - Theme details to be saved.
* @param {string} themeName - The name to identify the theme.
*/
async function saveToIndexedDB(theme, themeName) {
await localforage.setItem(`css_${themeName}`, {
css: theme.css,
className: theme.className,
images: theme.images,
});
for (const [cssVar, imageUrl] of Object.entries(theme.images)) {
try {
const response = await fetch(imageUrl);
if (!response.ok) {
console.error(`Failed to fetch image: ${response.statusText}`);
continue;
}
const blob = await response.blob();
await localforage.setItem(`images_${themeName}_${cssVar}`, blob);
} catch (error) {
console.error(`Error while handling image for ${cssVar}: ${error}`);
}
}
}
/**
* Applies theme from storage to the document.
* @param {string} themeName - The name of the theme to apply.
*/
async function applyTheme(themeName) {
const themeData = await localforage.getItem(`css_${themeName}`);
if (!themeData) {
throw new Error(`No theme data found for ${themeName}`);
}
const style = document.createElement("style");
style.innerHTML = themeData.css;
document.head.appendChild(style);
document.body.className = themeData.className;
if (themeData.images) {
for (const cssVar of Object.keys(themeData.images)) {
const imageData = await localforage.getItem(`images_${themeName}_${cssVar}`);
const objectURL = URL.createObjectURL(imageData);
document.documentElement.style.setProperty(cssVar, `url(${objectURL})`);
}
} else {
console.error("themeData.images is not defined!");
}
}
/**
* 🛠️ Utility Functions 🛠️
*/
/**
* Saves the list of available themes to local storage.
* @param {Array} themeList - An array of available themes.
*/
function saveAvailableThemes(themeList) {
localStorage.setItem("availableThemes", JSON.stringify(themeList));
}
/**
* Sets the currently selected theme in local storage.
* @param {string} themeName - The name of the selected theme.
*/
function setSelectedTheme(themeName) {
localStorage.setItem("selectedTheme", themeName);
}
/**
* 🚀 Main Function to Orchestrate Everything 🚀
*/
(async () => {
try {
const availableThemes = [
{ name: "dark", url: "https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/themes/test.json" },
];
saveAvailableThemes(availableThemes);
const themeToApply = availableThemes[0].name;
const themeData = await fetchThemeJSON(availableThemes[0].url);
await saveToIndexedDB(themeData, themeToApply);
setSelectedTheme(themeToApply);
await applyTheme(themeToApply);
} catch (error) {
console.error(`An error occurred: ${error}`);
}
})();
+2
View File
@@ -15,6 +15,7 @@ import { MessageHandler } from "./seqta/utils/MessageListener.js";
import { updateBgDurations } from "./seqta/ui/Animation.js";
import { updateAllColors } from "./seqta/ui/colors/Manager.js";
import { appendBackgroundToUI } from "./seqta/ui/ImageBackgrounds.js";
import { EnableThemes } from "./seqta/ui/Themes.js";
export let isChrome = window.chrome;
let SettingsClicked = false;
@@ -650,6 +651,7 @@ function main(storedSetting) {
if (storedSetting.onoff) {
console.log("[BetterSEQTA+] Enabled");
InjectStyles();
EnableThemes();
InjectCustomIcons();
updateAllColors(storedSetting);
ApplyCSSToHiddenMenuItems();
+93
View File
@@ -0,0 +1,93 @@
import localforage from "localforage";
// 🎨 Theme Management Functions 🎨
// Fetch theme details (CSS, images, className) from a given URL
async function fetchThemeJSON(url) {
console.log("Fetching theme from:", url);
const response = await fetch(url);
const data = await response.json();
const cssResponse = await fetch(data.css);
const cssText = await cssResponse.text();
return {
css: cssText,
images: data.images,
className: data.className
};
}
// Save theme details to storage via localForage
async function saveToIndexedDB(theme, themeName) {
console.log("Saving theme to IndexedDB:", themeName);
await localforage.setItem(`css_${themeName}`, { css: theme.css, className: theme.className, images: theme.images });
for (const [cssVar, imageUrl] of Object.entries(theme.images)) {
try {
const response = await fetch(imageUrl);
if (!response.ok) {
console.error(`Failed to fetch image: ${response.statusText}`);
continue;
}
const blob = await response.blob();
await localforage.setItem(`images_${themeName}_${cssVar}`, blob);
} catch (error) {
console.error(`Error while handling image for ${cssVar}: ${error}`);
}
}
}
// Apply theme from storage via localForage to document
async function applyTheme(themeName) {
console.log("Applying theme:", themeName);
const themeData = await localforage.getItem(`css_${themeName}`);
console.log("Retrieved Theme Data:", themeData); // Debugging info
const style = document.createElement("style");
style.innerHTML = themeData.css;
document.head.appendChild(style);
document.body.className = themeData.className;
if (themeData.images) {
for (const cssVar of Object.keys(themeData.images)) {
const imageData = await localforage.getItem(`images_${themeName}_${cssVar}`);
console.log(imageData);
const objectURL = URL.createObjectURL(imageData);
console.log("Applying image:", objectURL);
document.documentElement.style.setProperty(cssVar, `url(${objectURL})`);
}
} else {
console.error("themeData.images is not defined!");
}
}
// Save available themes to localStorage
function saveAvailableThemes(themeList) {
localStorage.setItem("availableThemes", JSON.stringify(themeList));
}
// Set the currently selected theme in localStorage
function setSelectedTheme(themeName) {
localStorage.setItem("selectedTheme", themeName);
}
// 🚀 Main function to orchestrate everything 🚀
export async function EnableThemes() {
console.log("Enabling themes!");
const availableThemes = [
{ name: "dark", url: "https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/themes/test.json" }
];
saveAvailableThemes(availableThemes);
const themeToApply = availableThemes[0].name;
const themeData = await fetchThemeJSON(availableThemes[0].url);
await saveToIndexedDB(themeData, themeToApply);
setSelectedTheme(themeToApply);
await applyTheme(themeToApply).catch((error) => {
console.error("Error while applying theme:", error);
});
}
+21 -3
View File
@@ -4,18 +4,19 @@ import { MenuOptionsOpen, OpenMenuOptions, closeSettings } from "../../SEQTA.js"
export class MessageHandler {
constructor() {
// Register this class as the message handler for the Chrome extension
chrome.runtime.onMessage.addListener(this.routeMessage.bind(this));
}
routeMessage(request) {
// You can use a switch-case or an object to route the message to the correct handler
switch (request.info) {
case "EditSidebar":
this.editSidebar();
break;
// Add more cases as needed
case "Theme":
console.log("Theme message received");
break;
default:
console.log("Unknown request info:", request.info);
@@ -31,3 +32,20 @@ export class MessageHandler {
// Add more methods for handling other message types
}
/* // Apply theme from the message
async function applyThemeFromMessage(themeData) {
const style = document.createElement("style");
style.innerHTML = themeData.css;
document.head.appendChild(style);
document.body.className = themeData.className;
if (themeData.images) {
for (const [cssVar, objectURL] of Object.entries(themeData.images)) {
document.documentElement.style.setProperty(cssVar, `url(${objectURL})`);
}
} else {
console.error("themeData.images is not defined!");
}
} */