more robust theme selector

This commit is contained in:
SethBurkart123
2023-11-02 17:11:02 +11:00
parent 46e86b9643
commit 8508169cd7
7 changed files with 246 additions and 109 deletions
@@ -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;
+14
View File
@@ -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;
+117 -6
View File
@@ -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;
-1
View File
@@ -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);
});
});
+5 -2
View File
@@ -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);
}
+15 -6
View File
@@ -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);