mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-06 03:34:40 +00:00
more robust theme selector
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
const presetBackgrounds = [
|
||||
// Images
|
||||
{
|
||||
id: 'image-preset-1',
|
||||
type: 'image',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-1.jpg',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-1-thumb.jpg',
|
||||
isPreset: true
|
||||
},
|
||||
{
|
||||
id: 'image-preset-2',
|
||||
type: 'image',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-2.jpg',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-2-thumb.jpg',
|
||||
isPreset: true
|
||||
},
|
||||
{
|
||||
id: 'image-preset-3',
|
||||
type: 'image',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-3.jpg',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-3-thumb.jpg',
|
||||
isPreset: true
|
||||
},
|
||||
{
|
||||
id: 'image-preset-4',
|
||||
type: 'image',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-4.jpg',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-4-thumb.jpg',
|
||||
isPreset: true
|
||||
},
|
||||
{
|
||||
id: 'image-preset-5',
|
||||
type: 'image',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-5.jpg',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-5-thumb.jpg',
|
||||
isPreset: true
|
||||
},
|
||||
{
|
||||
id: 'image-preset-6',
|
||||
type: 'image',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-6.jpg',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-6-thumb.jpg',
|
||||
isPreset: true
|
||||
},
|
||||
{
|
||||
id: 'image-preset-7',
|
||||
type: 'image',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-7.jpg',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-7-thumb.jpg',
|
||||
isPreset: true
|
||||
},
|
||||
|
||||
// Videos
|
||||
{
|
||||
id: 'video-preset-1',
|
||||
type: 'video',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/videos/animated-1.mp4',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/videos/animation-1-thumb.mp4',
|
||||
isPreset: true
|
||||
},
|
||||
{
|
||||
id: 'video-preset-2',
|
||||
type: 'video',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/videos/animation-2.mp4',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/videos/animation-2-thumb.mp4',
|
||||
isPreset: true
|
||||
}
|
||||
];
|
||||
|
||||
export default presetBackgrounds;
|
||||
@@ -0,0 +1,14 @@
|
||||
const themes = [
|
||||
{
|
||||
name: "Dark",
|
||||
url: "https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/themes/dark.json",
|
||||
coverImage: <img />,
|
||||
},
|
||||
{
|
||||
name: "Light",
|
||||
url: "https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/themes/light.json",
|
||||
coverImage: <img />,
|
||||
}
|
||||
];
|
||||
|
||||
export default themes;
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ChangeEvent, useEffect, useState } from "react";
|
||||
import { downloadPresetBackground, openDB, readAllData, writeData } from "../hooks/BackgroundDataLoader";
|
||||
import presetBackgrounds from "../assets/presetBackgrounds";
|
||||
import "./BackgroundSelector.css";
|
||||
|
||||
// Custom Types and Interfaces
|
||||
@@ -8,7 +9,7 @@ export interface Background {
|
||||
type: string;
|
||||
blob: Blob;
|
||||
url?: string;
|
||||
previewUrl?: string; // New field
|
||||
previewUrl?: string;
|
||||
isPreset?: boolean;
|
||||
isDownloaded?: boolean;
|
||||
}
|
||||
@@ -20,76 +21,6 @@ export default function BackgroundSelector() {
|
||||
const [downloadProgress, setDownloadProgress] = useState<Record<string, number>>({});
|
||||
const [isEditMode, setIsEditMode] = useState<boolean>(false);
|
||||
|
||||
|
||||
const presetBackgrounds = [
|
||||
// Images
|
||||
{
|
||||
id: 'image-preset-1',
|
||||
type: 'image',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-1.jpg',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-1-thumb.jpg',
|
||||
isPreset: true
|
||||
},
|
||||
{
|
||||
id: 'image-preset-2',
|
||||
type: 'image',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-2.jpg',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-2-thumb.jpg',
|
||||
isPreset: true
|
||||
},
|
||||
{
|
||||
id: 'image-preset-3',
|
||||
type: 'image',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-3.jpg',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-3-thumb.jpg',
|
||||
isPreset: true
|
||||
},
|
||||
{
|
||||
id: 'image-preset-4',
|
||||
type: 'image',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-4.jpg',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-4-thumb.jpg',
|
||||
isPreset: true
|
||||
},
|
||||
{
|
||||
id: 'image-preset-5',
|
||||
type: 'image',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-5.jpg',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-5-thumb.jpg',
|
||||
isPreset: true
|
||||
},
|
||||
{
|
||||
id: 'image-preset-6',
|
||||
type: 'image',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-6.jpg',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-6-thumb.jpg',
|
||||
isPreset: true
|
||||
},
|
||||
{
|
||||
id: 'image-preset-7',
|
||||
type: 'image',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-7.jpg',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-7-thumb.jpg',
|
||||
isPreset: true
|
||||
},
|
||||
|
||||
// Videos
|
||||
{
|
||||
id: 'video-preset-1',
|
||||
type: 'video',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/videos/animated-1.mp4',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/videos/animation-1-thumb.mp4',
|
||||
isPreset: true
|
||||
},
|
||||
{
|
||||
id: 'video-preset-2',
|
||||
type: 'video',
|
||||
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/videos/animation-2.mp4',
|
||||
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/videos/animation-2-thumb.mp4',
|
||||
isPreset: true
|
||||
}
|
||||
];
|
||||
|
||||
const handleFileChange = async (e: ChangeEvent<HTMLInputElement>): Promise<void> => {
|
||||
const file = e.target.files?.[0];
|
||||
if (!file) return;
|
||||
@@ -112,7 +43,7 @@ export default function BackgroundSelector() {
|
||||
setBackgrounds(dataWithUrls);
|
||||
};
|
||||
|
||||
const handlePresetClick = async (bg: Background): Promise<void> => {
|
||||
const handlePresetClick = async (bg: Background): Promise<void> => {
|
||||
if (bg.isPreset) {
|
||||
// Check if already exists in IndexedDB or is currently being downloaded
|
||||
const existingBackgrounds = await readAllData();
|
||||
@@ -135,7 +66,7 @@ const handlePresetClick = async (bg: Background): Promise<void> => {
|
||||
}
|
||||
selectBackground(bg.id);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const selectBackground = (fileId: string): void => {
|
||||
setSelectedBackground(fileId);
|
||||
|
||||
@@ -1,6 +1,35 @@
|
||||
const downloadTheme = (themeName: string, themeURL: string) => {
|
||||
import { useEffect, useState } from "react";
|
||||
import themesList from '../assets/themes';
|
||||
|
||||
interface Theme {
|
||||
name: string;
|
||||
url: string;
|
||||
isDownloaded: boolean;
|
||||
isLoading: boolean;
|
||||
coverImage: JSX.Element;
|
||||
}
|
||||
|
||||
interface ThemeList {
|
||||
themes: string[];
|
||||
}
|
||||
|
||||
const downloadTheme = async (themeName: string, themeURL: string) => {
|
||||
// send message to the background script
|
||||
chrome.runtime.sendMessage({
|
||||
const response = await chrome.runtime.sendMessage({
|
||||
type: 'currentTab',
|
||||
info: 'DownloadTheme',
|
||||
body: {
|
||||
themeName: themeName,
|
||||
themeURL: themeURL
|
||||
}
|
||||
});
|
||||
|
||||
console.log("Response: ", response);
|
||||
}
|
||||
|
||||
const setTheme = async (themeName: string, themeURL: string) => {
|
||||
// send message to the background script
|
||||
const response = await chrome.runtime.sendMessage({
|
||||
type: 'currentTab',
|
||||
info: 'SetTheme',
|
||||
body: {
|
||||
@@ -8,11 +37,93 @@ const downloadTheme = (themeName: string, themeURL: string) => {
|
||||
themeURL: themeURL
|
||||
}
|
||||
});
|
||||
|
||||
console.log("Response: ", response);
|
||||
}
|
||||
|
||||
const listThemes = async () => {
|
||||
// send message to the background script
|
||||
const response: ThemeList = await chrome.runtime.sendMessage({
|
||||
type: 'currentTab',
|
||||
info: 'ListThemes',
|
||||
body: {}
|
||||
});
|
||||
|
||||
// response.themes is an array of strings that are identical to the theme names that we loop over. Use this list to see which ones are downloaded and which ones need to see the download icon.
|
||||
console.log("Response: ", response);
|
||||
|
||||
return response.themes;
|
||||
}
|
||||
|
||||
const ThemeSelector = () => {
|
||||
const [themes, setThemes] = useState<Theme[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const initializeThemes = async () => {
|
||||
const downloaded = await listThemes();
|
||||
|
||||
const initializedThemes = themesList.map(theme => ({
|
||||
...theme,
|
||||
isDownloaded: downloaded.includes(theme.name),
|
||||
isLoading: false
|
||||
}));
|
||||
|
||||
setThemes(initializedThemes);
|
||||
};
|
||||
|
||||
initializeThemes();
|
||||
}, []);
|
||||
|
||||
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
|
||||
));
|
||||
|
||||
// Call the appropriate method based on whether the theme is downloaded
|
||||
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
|
||||
));
|
||||
}
|
||||
|
||||
// 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
|
||||
));
|
||||
};
|
||||
|
||||
export default function ThemeSelector() {
|
||||
return (
|
||||
<button onClick={() => downloadTheme('Dark', 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/themes/test.json')}>Dark</button>
|
||||
)
|
||||
}
|
||||
<div className="flex flex-col gap-4">
|
||||
{themes.map((theme) => (
|
||||
<button
|
||||
key={theme.name}
|
||||
className={`relative w-full h-16 flex justify-center items-center rounded-md overflow-hidden ${theme.isDownloaded ? 'bg-blue-500' : 'bg-green-500'} ${theme.isLoading ? 'opacity-50 cursor-not-allowed' : ''}`}
|
||||
onClick={() => handleThemeAction(theme.name, theme.url)}
|
||||
disabled={theme.isLoading}
|
||||
>
|
||||
{/* Position the cover image absolutely so that it doesn't affect the button's content layout */}
|
||||
<div className="absolute inset-0 z-0">
|
||||
{theme.coverImage}
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
{theme.isLoading ? (
|
||||
<div className="z-10 inline-block w-6 h-6 border-4 border-current rounded-full animate-spin border-t-transparent" role="status">
|
||||
<span className="sr-only">Loading...</span>
|
||||
</div>
|
||||
) : (
|
||||
<span className="z-10 text-lg font-bold text-white">{theme.name}</span>
|
||||
)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ThemeSelector;
|
||||
@@ -104,7 +104,6 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
case "currentTab":
|
||||
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
|
||||
chrome.tabs.sendMessage(tabs[0].id, request, function (response) {
|
||||
// send response from current tab to popup
|
||||
sendResponse(response);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -66,16 +66,19 @@ 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_", ""));
|
||||
};
|
||||
|
||||
export const downloadTheme = async (themeName, themeUrl) => {
|
||||
console.log(`Fetching theme ${themeName} from ${themeUrl}...`);
|
||||
const themeData = await fetchThemeJSON(themeUrl);
|
||||
await saveToIndexedDB(themeData, themeName);
|
||||
console.log(`Theme ${themeName} saved to IndexedDB`);
|
||||
return;
|
||||
};
|
||||
|
||||
export const setTheme = async (themeName, themeUrl) => {
|
||||
await downloadTheme(themeName, themeUrl);
|
||||
if (!(await themeExistsInDB(themeName))) {
|
||||
await downloadTheme(themeName, themeUrl);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/* global chrome */
|
||||
|
||||
import { MenuOptionsOpen, OpenMenuOptions, closeSettings } from "../../SEQTA.js";
|
||||
import { downloadTheme, setTheme } from "../ui/Themes.js";
|
||||
import { downloadTheme, listThemes, setTheme } from "../ui/Themes.js";
|
||||
|
||||
export class MessageHandler {
|
||||
constructor() {
|
||||
chrome.runtime.onMessage.addListener(this.routeMessage.bind(this));
|
||||
}
|
||||
|
||||
routeMessage(request) {
|
||||
routeMessage(request, sender, sendResponse) {
|
||||
switch (request.info) {
|
||||
|
||||
case "EditSidebar":
|
||||
@@ -16,11 +16,20 @@ export class MessageHandler {
|
||||
break;
|
||||
case "SetTheme":
|
||||
console.log(request);
|
||||
setTheme(request.body.themeName, request.body.themeURL);
|
||||
break;
|
||||
setTheme(request.body.themeName, request.body.themeURL).then(() => {
|
||||
sendResponse({ status: "success" });
|
||||
});
|
||||
return true;
|
||||
case "DownloadTheme":
|
||||
downloadTheme(request.body.themeURL, request.body.themeName);
|
||||
break;
|
||||
downloadTheme(request.body.themeName, request.body.themeURL).then(() => {
|
||||
sendResponse({ status: "success" });
|
||||
});
|
||||
return true;
|
||||
case "ListThemes":
|
||||
listThemes().then((themes) => {
|
||||
sendResponse({ themes });
|
||||
});
|
||||
return true;
|
||||
|
||||
default:
|
||||
console.log("Unknown request info:", request.info);
|
||||
|
||||
Reference in New Issue
Block a user