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 { 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,28 +85,61 @@ 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 (
|
||||||
<div className="my-2">
|
<div className="my-2">
|
||||||
@@ -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
@@ -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_", ""));
|
||||||
@@ -100,4 +118,36 @@ export const enableCurrentTheme = async () => {
|
|||||||
} else {
|
} else {
|
||||||
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.");
|
||||||
};
|
};
|
||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user