added theme disabling and theme selecting

This commit is contained in:
SethBurkart123
2023-11-02 18:09:02 +11:00
parent fb21eaeca1
commit 49bf19afd5
3 changed files with 122 additions and 24 deletions
+61 -18
View File
@@ -1,3 +1,5 @@
/* global chrome */
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import themesList from '../assets/themes'; import themesList from '../assets/themes';
@@ -55,8 +57,16 @@ const listThemes = async () => {
return response.themes; return response.themes;
} }
const disableTheme = async () => {
await chrome.runtime.sendMessage({
type: 'currentTab',
info: 'DisableTheme',
});
};
const ThemeSelector = () => { const ThemeSelector = () => {
const [themes, setThemes] = useState<Theme[]>([]); const [themes, setThemes] = useState<Theme[]>([]);
const [enabledThemeName, setEnabledThemeName] = useState<string>('');
useEffect(() => { useEffect(() => {
const initializeThemes = async () => { const initializeThemes = async () => {
@@ -75,27 +85,60 @@ const ThemeSelector = () => {
}, []); }, []);
const handleThemeAction = async (themeName: string, themeURL: string) => { const handleThemeAction = async (themeName: string, themeURL: string) => {
// Find the theme in the state and set its loading property to true // Start loading for the selected theme.
setThemes(prevThemes => prevThemes.map(theme => const startLoading = (name: string) => (
theme.name === themeName ? { ...theme, isLoading: true } : theme setThemes(prevThemes => prevThemes.map(theme =>
)); theme.name === name ? { ...theme, isLoading: true } : theme
))
);
// Call the appropriate method based on whether the theme is downloaded // Stop loading for the selected theme.
const stopLoading = (name: string) => (
setThemes(prevThemes => prevThemes.map(theme =>
theme.name === name ? { ...theme, isLoading: false } : theme
))
);
// Update the theme as downloaded.
const markAsDownloaded = (name: string) => (
setThemes(prevThemes => prevThemes.map(theme =>
theme.name === name ? { ...theme, isDownloaded: true } : theme
))
);
startLoading(themeName);
// Early return if theme is not found.
const theme = themes.find(t => t.name === themeName); const theme = themes.find(t => t.name === themeName);
if (theme && theme.isDownloaded) { if (!theme) {
await setTheme(themeName, themeURL); stopLoading(themeName);
} else { return;
await downloadTheme(themeName, themeURL);
// After downloading, update the theme to be marked as downloaded
setThemes(prevThemes => prevThemes.map(t =>
t.name === themeName ? { ...t, isDownloaded: true } : t
));
} }
// Once the action is complete, set the theme's loading property to false // If theme is downloaded and is the currently enabled theme, disable it.
setThemes(prevThemes => prevThemes.map(theme => if (theme.isDownloaded && themeName === enabledThemeName) {
theme.name === themeName ? { ...theme, isLoading: false } : theme await disableTheme();
)); setEnabledThemeName('');
stopLoading(themeName);
return;
}
// If theme is downloaded but not enabled, enable it.
if (theme.isDownloaded && themeName !== enabledThemeName) {
await setTheme(themeName, themeURL);
setEnabledThemeName(themeName);
stopLoading(themeName);
return;
}
// If theme is not downloaded, download and enable it.
if (!theme.isDownloaded) {
await downloadTheme(themeName, themeURL);
markAsDownloaded(themeName);
setEnabledThemeName(themeName);
}
stopLoading(themeName);
}; };
return ( return (
@@ -105,7 +148,7 @@ const ThemeSelector = () => {
{themes.map((theme) => ( {themes.map((theme) => (
<button <button
key={theme.name} key={theme.name}
className={`relative w-full h-16 flex justify-center items-center rounded-lg overflow-hidden bg-zinc-700 ${theme.isLoading ? 'cursor-not-allowed' : ''}`} className={`relative w-full h-16 flex justify-center items-center rounded-lg overflow-hidden bg-zinc-700 transition ring dark:ring-white ring-zinc-300 ${enabledThemeName == theme.name ? 'dark:ring-2 ring-4' : 'ring-0'} ${theme.isLoading ? 'cursor-not-allowed' : ''}`}
onClick={() => handleThemeAction(theme.name, theme.url)} onClick={() => handleThemeAction(theme.name, theme.url)}
disabled={theme.isLoading} disabled={theme.isLoading}
> >
+52 -2
View File
@@ -1,5 +1,8 @@
import localforage from "localforage"; import localforage from "localforage";
let currentThemeStyle = null;
let currentThemeClass = "";
// Utility function to fetch and parse JSON // Utility function to fetch and parse JSON
const fetchJSON = async (url) => { const fetchJSON = async (url) => {
const res = await fetch(url, {cache: "no-store"}); const res = await fetch(url, {cache: "no-store"});
@@ -44,15 +47,31 @@ const saveToIndexedDB = async (theme, themeName) => {
// Apply theme from storage via localForage to document // Apply theme from storage via localForage to document
const applyTheme = async (themeName) => { const applyTheme = async (themeName) => {
// Remove previous theme's style if it exists
if (currentThemeStyle) {
document.head.removeChild(currentThemeStyle);
currentThemeStyle = null;
}
// Remove previous theme's class if it exists
if (currentThemeClass) {
document.body.classList.remove(currentThemeClass);
currentThemeClass = "";
}
const { css, className, images } = await localforage.getItem(`css_${themeName}`); const { css, className, images } = await localforage.getItem(`css_${themeName}`);
// Apply CSS // Apply CSS
const style = document.createElement("style"); const style = document.createElement("style");
style.innerHTML = css; style.innerHTML = css;
document.head.appendChild(style); document.head.appendChild(style);
currentThemeStyle = style; // Keep track of the new style element
// Apply className // Apply className
if (className) document.body.classList.add(className); if (className) {
document.body.classList.add(className);
currentThemeClass = className; // Keep track of the new class
}
// Apply images // Apply images
if (images) { if (images) {
@@ -65,7 +84,6 @@ const applyTheme = async (themeName) => {
); );
} }
}; };
export const listThemes = async () => { export const listThemes = async () => {
const themes = await localforage.keys(); const themes = await localforage.keys();
return themes.filter((key) => key.startsWith("css_")).map((key) => key.replace("css_", "")); return themes.filter((key) => key.startsWith("css_")).map((key) => key.replace("css_", ""));
@@ -101,3 +119,35 @@ export const enableCurrentTheme = async () => {
console.log("No current theme set in localStorage."); console.log("No current theme set in localStorage.");
} }
}; };
export const disableTheme = async () => {
// Remove current theme's style if it exists
if (currentThemeStyle) {
document.head.removeChild(currentThemeStyle);
currentThemeStyle = null;
console.log("Current theme's style removed.");
}
// Remove current theme's class if it exists
if (currentThemeClass) {
document.body.classList.remove(currentThemeClass);
currentThemeClass = "";
console.log("Current theme's class removed.");
}
// Remove any applied image URLs from the root element
const currentTheme = localStorage.getItem("selectedTheme");
if (currentTheme) {
const themeData = await localforage.getItem(`css_${currentTheme}`);
if (themeData && themeData.images) {
Object.keys(themeData.images).forEach(cssVar => {
document.documentElement.style.removeProperty(cssVar);
});
}
console.log("Current theme's images removed.");
}
// Clear the selected theme from localStorage
localStorage.removeItem("selectedTheme");
console.log("Current theme disabled.");
};
+6 -1
View File
@@ -1,7 +1,7 @@
/* global chrome */ /* global chrome */
import { MenuOptionsOpen, OpenMenuOptions, closeSettings } from "../../SEQTA.js"; import { MenuOptionsOpen, OpenMenuOptions, closeSettings } from "../../SEQTA.js";
import { downloadTheme, listThemes, setTheme } from "../ui/Themes.js"; import { disableTheme, downloadTheme, listThemes, setTheme } from "../ui/Themes.js";
export class MessageHandler { export class MessageHandler {
constructor() { constructor() {
@@ -30,6 +30,11 @@ export class MessageHandler {
sendResponse({ themes }); sendResponse({ themes });
}); });
return true; return true;
case "DisableTheme":
disableTheme().then(() => {
sendResponse({ status: "success" });
});
return true;
default: default:
console.log("Unknown request info:", request.info); console.log("Unknown request info:", request.info);