mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-06 03:34:40 +00:00
added theme disabling and theme selecting
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
/* global chrome */
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import themesList from '../assets/themes';
|
||||
|
||||
@@ -55,8 +57,16 @@ const listThemes = async () => {
|
||||
return response.themes;
|
||||
}
|
||||
|
||||
const disableTheme = async () => {
|
||||
await chrome.runtime.sendMessage({
|
||||
type: 'currentTab',
|
||||
info: 'DisableTheme',
|
||||
});
|
||||
};
|
||||
|
||||
const ThemeSelector = () => {
|
||||
const [themes, setThemes] = useState<Theme[]>([]);
|
||||
const [enabledThemeName, setEnabledThemeName] = useState<string>('');
|
||||
|
||||
useEffect(() => {
|
||||
const initializeThemes = async () => {
|
||||
@@ -75,27 +85,60 @@ const ThemeSelector = () => {
|
||||
}, []);
|
||||
|
||||
const handleThemeAction = async (themeName: string, themeURL: string) => {
|
||||
// Find the theme in the state and set its loading property to true
|
||||
setThemes(prevThemes => prevThemes.map(theme =>
|
||||
theme.name === themeName ? { ...theme, isLoading: true } : theme
|
||||
));
|
||||
// Start loading for the selected theme.
|
||||
const startLoading = (name: string) => (
|
||||
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);
|
||||
if (theme && theme.isDownloaded) {
|
||||
await setTheme(themeName, themeURL);
|
||||
} else {
|
||||
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
|
||||
));
|
||||
if (!theme) {
|
||||
stopLoading(themeName);
|
||||
return;
|
||||
}
|
||||
|
||||
// Once the action is complete, set the theme's loading property to false
|
||||
setThemes(prevThemes => prevThemes.map(theme =>
|
||||
theme.name === themeName ? { ...theme, isLoading: false } : theme
|
||||
));
|
||||
// If theme is downloaded and is the currently enabled theme, disable it.
|
||||
if (theme.isDownloaded && themeName === enabledThemeName) {
|
||||
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 (
|
||||
@@ -105,7 +148,7 @@ const ThemeSelector = () => {
|
||||
{themes.map((theme) => (
|
||||
<button
|
||||
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)}
|
||||
disabled={theme.isLoading}
|
||||
>
|
||||
|
||||
+52
-2
@@ -1,5 +1,8 @@
|
||||
import localforage from "localforage";
|
||||
|
||||
let currentThemeStyle = null;
|
||||
let currentThemeClass = "";
|
||||
|
||||
// Utility function to fetch and parse JSON
|
||||
const fetchJSON = async (url) => {
|
||||
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
|
||||
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}`);
|
||||
|
||||
// Apply CSS
|
||||
const style = document.createElement("style");
|
||||
style.innerHTML = css;
|
||||
document.head.appendChild(style);
|
||||
currentThemeStyle = style; // Keep track of the new style element
|
||||
|
||||
// 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
|
||||
if (images) {
|
||||
@@ -65,7 +84,6 @@ const applyTheme = async (themeName) => {
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const listThemes = async () => {
|
||||
const themes = await localforage.keys();
|
||||
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.");
|
||||
}
|
||||
};
|
||||
|
||||
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.");
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
/* global chrome */
|
||||
|
||||
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 {
|
||||
constructor() {
|
||||
@@ -30,6 +30,11 @@ export class MessageHandler {
|
||||
sendResponse({ themes });
|
||||
});
|
||||
return true;
|
||||
case "DisableTheme":
|
||||
disableTheme().then(() => {
|
||||
sendResponse({ status: "success" });
|
||||
});
|
||||
return true;
|
||||
|
||||
default:
|
||||
console.log("Unknown request info:", request.info);
|
||||
|
||||
Reference in New Issue
Block a user